diff --git a/ports/Makefile b/ports/Makefile index d4cbf914..1be34914 100644 --- a/ports/Makefile +++ b/ports/Makefile @@ -22,6 +22,7 @@ lv2: libs ifeq ($(LINUX_EMBED),true) $(MAKE) -C arctican-function/LV2 $(MAKE) -C arctican-pilgrim/LV2 + $(MAKE) -C camomile/LV2 $(MAKE) -C drowaudio-distortion/LV2 $(MAKE) -C drowaudio-distortionshaper/LV2 $(MAKE) -C drowaudio-flanger/LV2 @@ -121,6 +122,7 @@ clean: # LV2 $(MAKE) clean -C arctican-function/LV2 $(MAKE) clean -C arctican-pilgrim/LV2 + $(MAKE) clean -C camomile/LV2 $(MAKE) clean -C dexed/LV2 $(MAKE) clean -C drowaudio-distortion/LV2 $(MAKE) clean -C drowaudio-distortionshaper/LV2 @@ -156,6 +158,7 @@ clean: # VST $(MAKE) clean -C arctican-function/VST $(MAKE) clean -C arctican-pilgrim/VST + $(MAKE) clean -C camomile/VST $(MAKE) clean -C dexed/VST $(MAKE) clean -C drowaudio-distortion/VST $(MAKE) clean -C drowaudio-distortionshaper/VST diff --git a/ports/camomile/LV2/premake.lua b/ports/camomile/LV2/premake.lua new file mode 100644 index 00000000..cd27674d --- /dev/null +++ b/ports/camomile/LV2/premake.lua @@ -0,0 +1,190 @@ + +dofile("../../../scripts/make-project.lua") + +package = make_juce_lv2_project("Camomile") + +package.defines = { package.defines, "PD=1", "USEAPI_DUMMY=1", "PD_INTERNAL=1", "PDINSTANCE=1", "PDTHREADS=1", "HAVE_LIBDL=1", "HAVE_UNISTD_H=1" } + +package.includepaths = { + package.includepaths, + "../source/LibPd/pure-data/src", + "../source/LibPd/libpd_wrapper" +} + + +if (os.getenv("LINUX_EMBED")) then +package.files = { + matchfiles ( + "../source/BinaryData.cpp", + "../source/PluginEnvironment.cpp", + "../source/PluginFileWatcher.cpp", + "../source/PluginParameter.cpp", + "../source/PluginParser.cpp", + "../source/PluginProcessor.cpp", + "../source/PluginProcessorBuses.cpp", + "../source/PluginProcessorReceive.cpp", + "../source/Pd/*.c", + "../source/Pd/*.cpp", + "../source/LibPd/pure-data/src/d_arithmetic.c", + "../source/LibPd/pure-data/src/d_array.c", + "../source/LibPd/pure-data/src/d_ctl.c", + "../source/LibPd/pure-data/src/d_dac.c", + "../source/LibPd/pure-data/src/d_delay.c", + "../source/LibPd/pure-data/src/d_fft.c", + "../source/LibPd/pure-data/src/d_fft_fftsg.c", + "../source/LibPd/pure-data/src/d_filter.c", + "../source/LibPd/pure-data/src/d_global.c", + "../source/LibPd/pure-data/src/d_math.c", + "../source/LibPd/pure-data/src/d_misc.c", + "../source/LibPd/pure-data/src/d_osc.c", + "../source/LibPd/pure-data/src/d_resample.c", + "../source/LibPd/pure-data/src/d_soundfile.c", + "../source/LibPd/pure-data/src/d_ugen.c", + "../source/LibPd/pure-data/src/g_all_guis.c", + "../source/LibPd/pure-data/src/g_array.c", + "../source/LibPd/pure-data/src/g_bang.c", + "../source/LibPd/pure-data/src/g_canvas.c", + "../source/LibPd/pure-data/src/g_clone.c", + "../source/LibPd/pure-data/src/g_editor.c", + "../source/LibPd/pure-data/src/g_graph.c", + "../source/LibPd/pure-data/src/g_guiconnect.c", + "../source/LibPd/pure-data/src/g_hdial.c", + "../source/LibPd/pure-data/src/g_hslider.c", + "../source/LibPd/pure-data/src/g_io.c", + "../source/LibPd/pure-data/src/g_mycanvas.c", + "../source/LibPd/pure-data/src/g_numbox.c", + "../source/LibPd/pure-data/src/g_readwrite.c", + "../source/LibPd/pure-data/src/g_rtext.c", + "../source/LibPd/pure-data/src/g_scalar.c", + "../source/LibPd/pure-data/src/g_template.c", + "../source/LibPd/pure-data/src/g_text.c", + "../source/LibPd/pure-data/src/g_toggle.c", + "../source/LibPd/pure-data/src/g_traversal.c", + "../source/LibPd/pure-data/src/g_vdial.c", + "../source/LibPd/pure-data/src/g_vslider.c", + "../source/LibPd/pure-data/src/g_vumeter.c", + "../source/LibPd/pure-data/src/m_atom.c", + "../source/LibPd/pure-data/src/m_binbuf.c", + "../source/LibPd/pure-data/src/m_class.c", + "../source/LibPd/pure-data/src/m_conf.c", + "../source/LibPd/pure-data/src/m_glob.c", + "../source/LibPd/pure-data/src/m_memory.c", + "../source/LibPd/pure-data/src/m_obj.c", + "../source/LibPd/pure-data/src/m_pd.c", + "../source/LibPd/pure-data/src/m_sched.c", + "../source/LibPd/pure-data/src/s_audio.c", + "../source/LibPd/pure-data/src/s_audio_dummy.c", + "../source/LibPd/pure-data/src/s_inter.c", + "../source/LibPd/pure-data/src/s_loader.c", + "../source/LibPd/pure-data/src/s_main.c", + "../source/LibPd/pure-data/src/s_path.c", + "../source/LibPd/pure-data/src/s_print.c", + "../source/LibPd/pure-data/src/s_utf8.c", + "../source/LibPd/pure-data/src/x_acoustics.c", + "../source/LibPd/pure-data/src/x_arithmetic.c", + "../source/LibPd/pure-data/src/x_array.c", + "../source/LibPd/pure-data/src/x_connective.c", + "../source/LibPd/pure-data/src/x_gui.c", + "../source/LibPd/pure-data/src/x_interface.c", + "../source/LibPd/pure-data/src/x_list.c", + "../source/LibPd/pure-data/src/x_midi.c", + "../source/LibPd/pure-data/src/x_misc.c", + "../source/LibPd/pure-data/src/x_net.c", + "../source/LibPd/pure-data/src/x_scalar.c", + "../source/LibPd/pure-data/src/x_text.c", + "../source/LibPd/pure-data/src/x_time.c", + "../source/LibPd/pure-data/src/x_vexp.c", + "../source/LibPd/pure-data/src/x_vexp_fun.c", + "../source/LibPd/pure-data/src/x_vexp_if.c", + "../source/LibPd/libpd_wrapper/s_libpdmidi.c", + "../source/LibPd/libpd_wrapper/x_libpdreceive.c", + "../source/LibPd/libpd_wrapper/z_hooks.c", + "../source/LibPd/libpd_wrapper/z_libpd.c", + "../../../libs/juce-plugin/JucePluginMain.cpp" + ) +} +else +package.files = { + matchfiles ( + "../source/*.cpp", + "../source/Pd/*.c", + "../source/Pd/*.cpp", + "../source/LibPd/pure-data/src/d_arithmetic.c", + "../source/LibPd/pure-data/src/d_array.c", + "../source/LibPd/pure-data/src/d_ctl.c", + "../source/LibPd/pure-data/src/d_dac.c", + "../source/LibPd/pure-data/src/d_delay.c", + "../source/LibPd/pure-data/src/d_fft.c", + "../source/LibPd/pure-data/src/d_fft_fftsg.c", + "../source/LibPd/pure-data/src/d_filter.c", + "../source/LibPd/pure-data/src/d_global.c", + "../source/LibPd/pure-data/src/d_math.c", + "../source/LibPd/pure-data/src/d_misc.c", + "../source/LibPd/pure-data/src/d_osc.c", + "../source/LibPd/pure-data/src/d_resample.c", + "../source/LibPd/pure-data/src/d_soundfile.c", + "../source/LibPd/pure-data/src/d_ugen.c", + "../source/LibPd/pure-data/src/g_all_guis.c", + "../source/LibPd/pure-data/src/g_array.c", + "../source/LibPd/pure-data/src/g_bang.c", + "../source/LibPd/pure-data/src/g_canvas.c", + "../source/LibPd/pure-data/src/g_clone.c", + "../source/LibPd/pure-data/src/g_editor.c", + "../source/LibPd/pure-data/src/g_graph.c", + "../source/LibPd/pure-data/src/g_guiconnect.c", + "../source/LibPd/pure-data/src/g_hdial.c", + "../source/LibPd/pure-data/src/g_hslider.c", + "../source/LibPd/pure-data/src/g_io.c", + "../source/LibPd/pure-data/src/g_mycanvas.c", + "../source/LibPd/pure-data/src/g_numbox.c", + "../source/LibPd/pure-data/src/g_readwrite.c", + "../source/LibPd/pure-data/src/g_rtext.c", + "../source/LibPd/pure-data/src/g_scalar.c", + "../source/LibPd/pure-data/src/g_template.c", + "../source/LibPd/pure-data/src/g_text.c", + "../source/LibPd/pure-data/src/g_toggle.c", + "../source/LibPd/pure-data/src/g_traversal.c", + "../source/LibPd/pure-data/src/g_vdial.c", + "../source/LibPd/pure-data/src/g_vslider.c", + "../source/LibPd/pure-data/src/g_vumeter.c", + "../source/LibPd/pure-data/src/m_atom.c", + "../source/LibPd/pure-data/src/m_binbuf.c", + "../source/LibPd/pure-data/src/m_class.c", + "../source/LibPd/pure-data/src/m_conf.c", + "../source/LibPd/pure-data/src/m_glob.c", + "../source/LibPd/pure-data/src/m_memory.c", + "../source/LibPd/pure-data/src/m_obj.c", + "../source/LibPd/pure-data/src/m_pd.c", + "../source/LibPd/pure-data/src/m_sched.c", + "../source/LibPd/pure-data/src/s_audio.c", + "../source/LibPd/pure-data/src/s_audio_dummy.c", + "../source/LibPd/pure-data/src/s_inter.c", + "../source/LibPd/pure-data/src/s_loader.c", + "../source/LibPd/pure-data/src/s_main.c", + "../source/LibPd/pure-data/src/s_path.c", + "../source/LibPd/pure-data/src/s_print.c", + "../source/LibPd/pure-data/src/s_utf8.c", + "../source/LibPd/pure-data/src/x_acoustics.c", + "../source/LibPd/pure-data/src/x_arithmetic.c", + "../source/LibPd/pure-data/src/x_array.c", + "../source/LibPd/pure-data/src/x_connective.c", + "../source/LibPd/pure-data/src/x_gui.c", + "../source/LibPd/pure-data/src/x_interface.c", + "../source/LibPd/pure-data/src/x_list.c", + "../source/LibPd/pure-data/src/x_midi.c", + "../source/LibPd/pure-data/src/x_misc.c", + "../source/LibPd/pure-data/src/x_net.c", + "../source/LibPd/pure-data/src/x_scalar.c", + "../source/LibPd/pure-data/src/x_text.c", + "../source/LibPd/pure-data/src/x_time.c", + "../source/LibPd/pure-data/src/x_vexp.c", + "../source/LibPd/pure-data/src/x_vexp_fun.c", + "../source/LibPd/pure-data/src/x_vexp_if.c", + "../source/LibPd/libpd_wrapper/s_libpdmidi.c", + "../source/LibPd/libpd_wrapper/x_libpdreceive.c", + "../source/LibPd/libpd_wrapper/z_hooks.c", + "../source/LibPd/libpd_wrapper/z_libpd.c", + "../../../libs/juce-plugin/JucePluginMain.cpp" + ) +} +end diff --git a/ports/camomile/VST/premake.lua b/ports/camomile/VST/premake.lua new file mode 100644 index 00000000..03d001aa --- /dev/null +++ b/ports/camomile/VST/premake.lua @@ -0,0 +1,96 @@ + +dofile("../../../scripts/make-project.lua") + +package = make_juce_vst_project("Camomile") + +package.defines = { package.defines, "PD=1", "USEAPI_DUMMY=1", "PD_INTERNAL=1", "PDINSTANCE=1", "PDTHREADS=1", "HAVE_LIBDL=1", "HAVE_UNISTD_H=1" } + +package.includepaths = { + package.includepaths, + "../source/LibPd/pure-data/src", + "../source/LibPd/libpd_wrapper" +} + +package.files = { + matchfiles ( + "../source/*.cpp", + "../source/Pd/*.c", + "../source/Pd/*.cpp", + "../source/LibPd/pure-data/src/d_arithmetic.c", + "../source/LibPd/pure-data/src/d_array.c", + "../source/LibPd/pure-data/src/d_ctl.c", + "../source/LibPd/pure-data/src/d_dac.c", + "../source/LibPd/pure-data/src/d_delay.c", + "../source/LibPd/pure-data/src/d_fft.c", + "../source/LibPd/pure-data/src/d_fft_fftsg.c", + "../source/LibPd/pure-data/src/d_filter.c", + "../source/LibPd/pure-data/src/d_global.c", + "../source/LibPd/pure-data/src/d_math.c", + "../source/LibPd/pure-data/src/d_misc.c", + "../source/LibPd/pure-data/src/d_osc.c", + "../source/LibPd/pure-data/src/d_resample.c", + "../source/LibPd/pure-data/src/d_soundfile.c", + "../source/LibPd/pure-data/src/d_ugen.c", + "../source/LibPd/pure-data/src/g_all_guis.c", + "../source/LibPd/pure-data/src/g_array.c", + "../source/LibPd/pure-data/src/g_bang.c", + "../source/LibPd/pure-data/src/g_canvas.c", + "../source/LibPd/pure-data/src/g_clone.c", + "../source/LibPd/pure-data/src/g_editor.c", + "../source/LibPd/pure-data/src/g_graph.c", + "../source/LibPd/pure-data/src/g_guiconnect.c", + "../source/LibPd/pure-data/src/g_hdial.c", + "../source/LibPd/pure-data/src/g_hslider.c", + "../source/LibPd/pure-data/src/g_io.c", + "../source/LibPd/pure-data/src/g_mycanvas.c", + "../source/LibPd/pure-data/src/g_numbox.c", + "../source/LibPd/pure-data/src/g_readwrite.c", + "../source/LibPd/pure-data/src/g_rtext.c", + "../source/LibPd/pure-data/src/g_scalar.c", + "../source/LibPd/pure-data/src/g_template.c", + "../source/LibPd/pure-data/src/g_text.c", + "../source/LibPd/pure-data/src/g_toggle.c", + "../source/LibPd/pure-data/src/g_traversal.c", + "../source/LibPd/pure-data/src/g_vdial.c", + "../source/LibPd/pure-data/src/g_vslider.c", + "../source/LibPd/pure-data/src/g_vumeter.c", + "../source/LibPd/pure-data/src/m_atom.c", + "../source/LibPd/pure-data/src/m_binbuf.c", + "../source/LibPd/pure-data/src/m_class.c", + "../source/LibPd/pure-data/src/m_conf.c", + "../source/LibPd/pure-data/src/m_glob.c", + "../source/LibPd/pure-data/src/m_memory.c", + "../source/LibPd/pure-data/src/m_obj.c", + "../source/LibPd/pure-data/src/m_pd.c", + "../source/LibPd/pure-data/src/m_sched.c", + "../source/LibPd/pure-data/src/s_audio.c", + "../source/LibPd/pure-data/src/s_audio_dummy.c", + "../source/LibPd/pure-data/src/s_inter.c", + "../source/LibPd/pure-data/src/s_loader.c", + "../source/LibPd/pure-data/src/s_main.c", + "../source/LibPd/pure-data/src/s_path.c", + "../source/LibPd/pure-data/src/s_print.c", + "../source/LibPd/pure-data/src/s_utf8.c", + "../source/LibPd/pure-data/src/x_acoustics.c", + "../source/LibPd/pure-data/src/x_arithmetic.c", + "../source/LibPd/pure-data/src/x_array.c", + "../source/LibPd/pure-data/src/x_connective.c", + "../source/LibPd/pure-data/src/x_gui.c", + "../source/LibPd/pure-data/src/x_interface.c", + "../source/LibPd/pure-data/src/x_list.c", + "../source/LibPd/pure-data/src/x_midi.c", + "../source/LibPd/pure-data/src/x_misc.c", + "../source/LibPd/pure-data/src/x_net.c", + "../source/LibPd/pure-data/src/x_scalar.c", + "../source/LibPd/pure-data/src/x_text.c", + "../source/LibPd/pure-data/src/x_time.c", + "../source/LibPd/pure-data/src/x_vexp.c", + "../source/LibPd/pure-data/src/x_vexp_fun.c", + "../source/LibPd/pure-data/src/x_vexp_if.c", + "../source/LibPd/libpd_wrapper/s_libpdmidi.c", + "../source/LibPd/libpd_wrapper/x_libpdreceive.c", + "../source/LibPd/libpd_wrapper/z_hooks.c", + "../source/LibPd/libpd_wrapper/z_libpd.c", + "../../../libs/juce-plugin/JucePluginMain.cpp" + ) +} diff --git a/ports/camomile/source/BinaryData.cpp b/ports/camomile/source/BinaryData.cpp new file mode 100644 index 00000000..458bf2b6 --- /dev/null +++ b/ports/camomile/source/BinaryData.cpp @@ -0,0 +1,4928 @@ +/* ==================================== JUCER_BINARY_RESOURCE ==================================== + + This is an auto-generated file: Any edits you make may be overwritten! + +*/ + +namespace BinaryData +{ + +//================== CreditsAU ================== +static const unsigned char temp_binary_data_0[] = +"Camomile is a free and open-source audio plugin with Pure Data embedded that offers to load and to control patches inside a digital audio workstation.\n" +"\n" +"Version: 1.0.6\n" +"Author: Pierre Guillot\n" +"Organizations: CICM | Universit\xc3\xa9 Paris 8\n" +"Website: github.com/pierreguillot/camomile\n" +"Credits:\n" +"\xe2\x80\xa2 Pure Data by Miller Puckette and others\n" +"\xe2\x80\xa2 libpd by the Peter Brinkmann, Dan Wilcox and others\n" +"\xe2\x80\xa2 JUCE by ROLI Ltd.\n" +"\xe2\x80\xa2 MoodyCamel by Cameron Desrochers\n" +"\xe2\x80\xa2 Console icons by Gregor Cresnar\n"; + +const char* CreditsAU = (const char*) temp_binary_data_0; + +//================== CreditsLV2 ================== +static const unsigned char temp_binary_data_1[] = +"Camomile is a free and open-source audio plugin with Pure Data embedded that offers to load and to control patches inside a digital audio workstation.\n" +"\n" +"Version: 1.0.6\n" +"Author: Pierre Guillot\n" +"Organizations: CICM | Universit\xc3\xa9 Paris 8\n" +"Website: github.com/pierreguillot/camomile\n" +"Credits:\n" +"\xe2\x80\xa2 Pure Data by Miller Puckette and others\n" +"\xe2\x80\xa2 libpd by the Peter Brinkmann, Dan Wilcox and others\n" +"\xe2\x80\xa2 JUCE by ROLI Ltd.\n" +"\xe2\x80\xa2 LV2 PlugIn Technology developed by Steve Harris, David Robillard and others\n" +"\xe2\x80\xa2 JUCE LV2 support based on Filipe Coelho JUCE LV2 integration\n" +"\xe2\x80\xa2 MoodyCamel by Cameron Desrochers\n" +"\xe2\x80\xa2 Console icons by Gregor Cresnar\n"; + +const char* CreditsLV2 = (const char*) temp_binary_data_1; + +//================== CreditsVST ================== +static const unsigned char temp_binary_data_2[] = +"Camomile is a free and open-source audio plugin with Pure Data embedded that offers to load and to control patches inside a digital audio workstation.\n" +"\n" +"Version: 1.0.6\n" +"Author: Pierre Guillot\n" +"Organizations: CICM | Universit\xc3\xa9 Paris 8\n" +"Website: github.com/pierreguillot/camomile\n" +"Credits:\n" +"\xe2\x80\xa2 Pure Data by Miller Puckette and others\n" +"\xe2\x80\xa2 libpd by the Peter Brinkmann, Dan Wilcox and others\n" +"\xe2\x80\xa2 JUCE by ROLI Ltd.\n" +"\xe2\x80\xa2 VST PlugIn Technology by Steinberg Media Technologies\n" +"\xe2\x80\xa2 MoodyCamel by Cameron Desrochers\n" +"\xe2\x80\xa2 Console icons by Gregor Cresnar\n"; + +const char* CreditsVST = (const char*) temp_binary_data_2; + +//================== DejaVuSansMono.ttf ================== +static const unsigned char temp_binary_data_3[] = +{ 0,1,0,0,0,18,1,0,0,4,0,32,70,70,84,77,115,193,244,240,0,0,1,44,0,0,0,28,71,68,69,70,128,214,115,112,0,0,1,72,0,0,0,176,71,80,79,83,47,32,213,201,0,0,1,248,0,0,57,246,71,83,85,66,92,138,144,134,0,0,59,240,0,0,4,212,79,83,47,50,140,252,138,178,0,0,64,196, +0,0,0,86,99,109,97,112,95,210,149,209,0,0,65,28,0,0,22,78,99,118,116,32,233,151,7,12,0,0,87,108,0,0,2,48,102,112,103,109,91,2,107,223,0,0,89,156,0,0,0,172,103,97,115,112,0,7,0,7,0,0,90,72,0,0,0,12,103,108,121,102,154,139,23,178,0,0,90,84,0,3,227,8,104, +101,97,100,7,255,0,224,0,4,61,92,0,0,0,54,104,104,101,97,8,184,2,7,0,4,61,148,0,0,0,36,104,109,116,120,73,16,76,2,0,4,61,184,0,0,26,106,108,111,99,97,24,162,167,80,0,4,88,36,0,0,52,200,109,97,120,112,18,215,4,39,0,4,140,236,0,0,0,32,110,97,109,101,96, +231,234,140,0,4,141,12,0,0,33,21,112,111,115,116,250,158,100,234,0,4,174,36,0,0,125,165,112,114,101,112,58,199,192,7,0,5,43,204,0,0,7,27,0,0,0,1,0,0,0,0,204,61,162,207,0,0,0,0,211,194,41,16,0,0,0,0,211,194,41,16,0,1,0,0,0,14,0,0,0,168,0,0,0,0,0,2,0,25, +0,3,2,135,0,1,2,136,2,153,0,3,2,154,2,154,0,1,2,155,2,161,0,3,2,162,2,163,0,1,2,164,2,168,0,3,2,169,2,170,0,1,2,171,2,175,0,3,2,176,2,176,0,1,2,177,2,185,0,3,2,186,2,192,0,1,2,193,2,198,0,3,2,199,2,199,0,1,2,200,2,200,0,3,2,201,4,123,0,1,4,124,4,135, +0,3,4,136,4,207,0,1,4,208,4,208,0,3,4,209,4,210,0,1,4,211,4,224,0,3,4,225,11,225,0,1,11,226,11,227,0,2,11,228,12,175,0,1,12,176,12,183,0,2,12,184,13,48,0,1,0,4,0,0,0,2,0,0,0,1,0,0,0,10,0,176,0,248,0,6,68,70,76,84,0,38,97,114,97,98,0,48,99,121,114,108, +0,62,103,114,101,107,0,80,108,97,111,32,0,92,108,97,116,110,0,106,0,4,0,0,0,0,255,255,0,0,0,4,0,0,0,0,255,255,0,2,0,0,0,3,0,10,0,1,83,82,66,32,0,10,0,0,255,255,0,1,0,1,0,4,0,0,0,0,255,255,0,1,0,1,0,4,0,0,0,0,255,255,0,2,0,2,0,4,0,52,0,8,73,83,77,32,0, +52,75,83,77,32,0,52,76,83,77,32,0,52,77,79,76,32,0,52,78,83,77,32,0,52,82,79,77,32,0,52,83,75,83,32,0,52,83,83,77,32,0,52,0,0,255,255,0,1,0,1,0,5,109,97,114,107,0,32,109,97,114,107,0,44,109,97,114,107,0,52,109,107,109,107,0,58,114,116,98,100,0,66,0,0, +0,4,0,2,0,3,0,4,0,5,0,0,0,2,0,6,0,7,0,0,0,1,0,8,0,0,0,2,0,0,0,1,0,0,0,1,0,9,0,10,0,22,0,30,0,38,0,46,0,54,0,62,0,70,0,80,0,88,0,96,0,6,0,1,0,1,0,82,0,6,0,1,0,1,0,120,0,5,0,1,0,1,0,192,0,4,0,1,0,1,1,154,0,5,0,1,0,1,9,124,0,4,0,1,0,1,10,158,0,4,0,0,0,2, +18,132,27,186,0,1,0,0,0,1,53,246,0,4,0,0,0,1,54,30,0,1,0,8,0,1,56,134,0,1,0,28,0,22,0,1,0,34,0,12,0,1,0,4,0,1,2,112,253,228,0,1,0,1,4,134,0,1,0,1,4,129,0,1,0,0,0,6,0,1,2,104,0,0,0,1,0,38,0,30,0,1,0,48,0,12,0,2,0,6,0,12,0,1,2,99,7,34,0,1,2,99,6,224,0, +1,0,2,4,130,4,133,0,1,0,3,4,127,4,128,4,131,0,3,0,0,0,14,0,0,0,20,0,0,0,26,0,1,2,93,4,106,0,1,2,93,4,106,0,1,2,98,4,106,0,1,0,184,0,174,0,1,0,194,0,12,0,8,0,18,0,36,0,54,0,72,0,90,0,108,0,126,0,144,0,2,0,6,0,12,0,1,3,224,0,80,0,1,3,124,0,72,0,2,0,6,0, +12,0,1,3,48,255,224,0,1,2,172,255,220,0,2,0,6,0,12,0,1,3,224,0,80,0,1,3,124,0,72,0,2,0,6,0,12,0,1,3,60,255,136,0,1,2,80,255,132,0,2,0,6,0,12,0,1,3,168,0,44,0,1,1,32,253,220,0,2,0,6,0,12,0,1,3,84,255,96,0,1,1,12,253,220,0,2,0,6,0,12,0,1,3,224,0,80,0,1, +3,124,0,72,0,2,0,6,0,12,0,1,2,12,255,164,0,1,3,16,0,32,0,2,0,1,12,176,12,183,0,0,0,1,0,3,4,126,4,129,4,134,0,3,0,0,0,14,0,0,0,20,0,0,0,26,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,7,192,7,110,0,1,7,202,0,12,0,236,1,218,1,224,1,230,1,236,1,242,1,248, +1,254,2,4,2,10,2,16,2,22,2,28,2,34,2,40,2,46,2,52,2,58,2,64,2,70,2,76,2,82,2,88,2,94,2,100,2,106,2,112,2,118,2,124,2,130,2,136,2,142,2,148,2,154,2,160,2,166,2,172,2,178,2,184,2,190,2,196,2,202,2,208,2,214,2,220,2,226,2,232,2,238,2,244,2,250,3,0,3,6,3, +12,3,18,3,24,3,30,3,36,3,42,3,48,3,54,3,60,3,66,3,72,3,78,3,84,3,90,3,96,3,102,3,108,3,114,3,120,3,126,3,132,3,138,3,144,3,150,3,156,3,162,3,168,3,174,3,180,3,186,3,192,3,198,3,204,3,210,3,216,3,222,3,228,3,234,3,240,3,246,3,252,4,2,4,8,4,14,4,20,4,26, +4,32,4,38,4,44,4,50,4,56,4,62,4,68,4,74,4,80,4,86,4,92,4,98,4,104,4,110,4,116,4,122,4,128,4,134,4,140,4,146,4,152,4,158,4,164,4,170,4,176,4,182,4,188,4,194,4,200,4,206,4,212,4,218,4,224,4,230,4,236,4,242,4,248,4,254,5,4,5,10,5,16,5,22,5,28,5,34,5,40, +5,46,5,52,5,58,5,64,5,70,5,76,5,82,5,88,5,94,5,100,5,106,5,112,5,118,5,124,5,130,5,136,5,142,5,148,5,154,5,160,5,166,5,172,5,178,5,184,5,190,5,196,5,202,5,208,5,214,5,220,5,226,5,232,5,238,5,244,5,250,6,0,6,6,6,12,6,18,6,24,6,30,6,36,6,42,6,48,6,54,6, +60,6,66,6,72,6,78,6,84,6,90,6,96,6,102,6,108,6,114,6,120,6,126,6,132,6,138,6,144,6,150,6,156,6,162,6,168,6,174,6,180,6,186,6,192,6,198,6,204,6,210,6,216,6,222,6,228,6,234,6,240,6,246,6,252,7,2,7,8,7,14,7,20,7,26,7,32,7,38,7,44,7,50,7,56,7,62,7,68,7,74, +7,80,7,86,7,92,0,1,2,88,0,0,0,1,2,100,253,223,0,1,1,212,2,124,0,1,2,100,255,178,0,1,2,104,254,136,0,1,2,48,255,96,0,1,2,116,255,88,0,1,2,116,255,88,0,1,1,252,253,204,0,1,2,12,253,208,0,1,2,60,253,183,0,1,2,8,255,124,0,1,2,8,255,140,0,1,2,48,253,224,0, +1,2,48,253,236,0,1,2,104,254,76,0,1,2,160,254,132,0,1,3,40,254,220,0,1,3,32,254,192,0,1,1,84,255,112,0,1,1,108,255,120,0,1,2,144,253,204,0,1,2,136,253,208,0,1,2,96,255,120,0,1,2,60,255,68,0,1,2,40,254,68,0,1,1,252,255,100,0,1,2,20,254,124,0,1,2,116,255, +88,0,1,2,76,254,92,0,1,2,56,255,40,0,1,2,80,253,220,0,1,2,64,254,180,0,1,2,64,253,224,0,1,2,116,255,88,0,1,2,116,255,88,0,1,2,52,253,232,0,1,2,96,253,224,0,1,2,116,255,88,0,1,2,100,253,236,0,1,2,12,253,231,0,1,2,52,253,220,0,1,2,88,253,220,0,1,2,72,253, +224,0,1,2,46,253,228,0,1,2,17,253,227,0,1,1,212,255,68,0,1,2,53,255,106,0,1,2,84,255,106,0,1,2,96,255,95,0,1,2,13,254,112,0,1,2,105,253,168,0,1,2,70,253,168,0,1,2,87,253,218,0,1,2,87,253,218,0,1,2,133,253,168,0,1,2,64,253,168,0,1,2,84,253,218,0,1,2,81, +253,218,0,1,2,88,253,168,0,1,2,58,253,168,0,1,2,66,253,218,0,1,2,96,253,218,0,1,2,130,255,106,0,1,2,76,255,106,0,1,2,91,255,155,0,1,2,90,255,156,0,1,2,91,255,106,0,1,2,73,255,106,0,1,2,87,255,156,0,1,2,84,255,156,0,1,2,76,255,106,0,1,2,52,255,106,0,1, +2,75,255,156,0,1,2,93,255,156,0,1,1,212,255,76,0,1,1,148,255,64,0,1,1,244,255,106,0,1,2,86,255,106,0,1,1,224,255,56,0,1,1,136,255,56,0,1,1,244,255,106,0,1,2,98,255,106,0,1,2,116,253,168,0,1,2,92,253,168,0,1,1,172,254,12,0,1,2,88,254,12,0,1,2,84,253,168, +0,1,2,72,253,168,0,1,1,132,255,6,0,1,2,88,255,6,0,1,2,84,253,168,0,1,2,56,253,167,0,1,1,184,253,228,0,1,2,88,254,12,0,1,2,104,253,168,0,1,2,100,253,168,0,1,1,196,253,228,0,1,2,88,254,12,0,1,1,244,254,12,0,1,1,244,254,12,0,1,1,244,254,12,0,1,1,244,254, +12,0,1,2,63,255,106,0,1,1,198,255,106,0,1,1,44,255,106,0,1,1,44,255,106,0,1,2,84,255,95,0,1,1,238,255,106,0,1,1,44,255,106,0,1,1,44,255,106,0,1,2,84,255,100,0,1,2,84,255,100,0,1,1,184,255,100,0,1,2,16,255,100,0,1,2,76,254,112,0,1,1,152,254,112,0,1,2, +79,254,162,0,1,2,91,254,162,0,1,2,192,0,28,0,1,2,100,253,216,0,1,2,204,253,216,0,1,2,24,255,128,0,1,2,100,255,88,0,1,2,100,255,120,0,1,2,176,255,88,0,1,2,100,254,104,0,1,2,28,254,104,0,1,2,68,254,140,0,1,2,88,254,140,0,1,2,44,255,76,0,1,2,108,255,132, +0,1,2,108,255,132,0,1,2,84,255,112,0,1,2,60,255,132,0,1,2,88,255,124,0,1,2,108,255,132,0,1,2,72,255,128,0,1,2,72,255,124,0,1,2,84,255,116,0,1,2,0,253,144,0,1,2,0,253,144,0,1,2,8,254,136,0,1,2,12,254,108,0,1,2,0,253,144,0,1,2,0,253,144,0,1,1,60,255,132, +0,1,1,84,255,112,0,1,2,0,253,144,0,1,2,0,253,144,0,1,1,124,255,128,0,1,1,68,255,92,0,1,2,56,255,92,0,1,2,56,255,92,0,1,2,56,255,92,0,1,2,56,255,92,0,1,1,188,253,192,0,1,1,140,253,189,0,1,1,188,253,192,0,1,1,156,253,188,0,1,1,152,254,12,0,1,1,88,254,16, +0,1,1,44,255,108,0,1,1,16,255,100,0,1,1,92,254,28,0,1,1,9,254,24,0,1,1,44,255,108,0,1,1,44,255,108,0,1,1,120,254,20,0,1,1,68,254,17,0,1,1,44,255,108,0,1,1,44,255,108,0,1,1,76,254,16,0,1,1,32,254,24,0,1,1,44,255,108,0,1,1,4,255,108,0,1,0,240,255,108,0, +1,0,216,255,108,0,1,0,240,255,108,0,1,0,208,255,112,0,1,0,240,255,108,0,1,0,208,255,104,0,1,0,240,255,108,0,1,0,220,255,108,0,1,1,122,253,215,0,1,1,122,253,215,0,1,1,224,255,147,0,1,2,94,255,141,0,1,1,122,253,215,0,1,1,122,253,215,0,1,1,146,255,159,0, +1,2,94,255,159,0,1,2,94,255,45,0,1,2,100,255,15,0,1,1,158,255,117,0,1,2,106,255,129,0,1,1,224,254,25,0,1,1,224,253,185,0,1,1,56,255,141,0,1,2,106,255,129,0,1,2,58,255,75,0,1,1,218,255,81,0,1,0,216,255,129,0,1,0,162,255,93,0,1,2,88,254,109,0,1,1,254,254, +97,0,1,2,100,255,135,0,1,2,106,255,117,0,1,3,18,255,117,0,1,2,172,254,163,0,1,2,70,255,21,0,1,2,88,255,39,0,1,1,254,254,85,0,1,1,194,253,197,0,1,2,64,255,129,0,1,2,76,255,123,0,1,2,82,255,75,0,1,2,82,255,111,0,1,1,176,255,39,0,1,2,16,253,210,0,1,2,76, +253,233,0,1,2,4,253,209,0,1,2,46,254,145,0,1,2,28,253,173,0,1,1,146,253,188,0,1,2,58,254,139,0,1,2,82,254,133,0,1,2,120,253,208,0,1,2,116,255,88,0,1,2,68,253,216,0,1,1,244,253,208,0,1,2,52,253,224,0,1,2,69,253,223,0,1,2,8,254,110,0,1,2,80,253,220,0,1, +2,13,254,112,0,2,0,13,4,87,4,87,0,0,4,91,4,123,0,1,4,151,4,167,0,34,11,228,12,31,0,51,12,34,12,37,0,111,12,40,12,43,0,115,12,59,12,59,0,119,12,66,12,67,0,120,12,70,12,170,0,122,12,172,12,175,0,223,13,34,13,39,0,227,13,41,13,41,0,233,13,43,13,44,0,234, +0,1,0,3,4,126,4,129,4,134,0,3,0,0,0,14,0,0,0,20,0,0,0,26,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,0,184,0,174,0,1,0,206,0,12,0,8,0,18,0,36,0,54,0,72,0,90,0,108,0,126,0,144,0,2,0,6,0,12,0,1,3,156,6,104,0,1,0,147,7,53,0,2,0,6,0,12,0,1,3,156,6,104, +0,1,0,91,7,25,0,2,0,6,0,12,0,1,3,156,6,104,0,1,0,155,7,246,0,2,0,6,0,12,0,1,3,84,6,108,0,1,0,43,7,250,0,2,0,6,0,12,0,1,3,156,6,104,0,1,0,223,5,221,0,2,0,6,0,12,0,1,3,156,6,104,0,1,0,223,5,221,0,2,0,6,0,12,0,1,3,156,6,104,0,1,0,223,5,221,0,2,0,6,0,12, +0,1,3,92,6,104,0,1,0,159,5,221,0,2,0,1,12,176,12,183,0,0,0,1,0,9,4,124,4,125,4,127,4,128,4,130,4,131,4,132,4,133,4,135,0,9,0,0,0,38,0,0,0,44,0,0,0,50,0,0,0,56,0,0,0,62,0,0,0,68,0,0,0,74,0,0,0,80,0,0,0,86,0,1,2,93,4,106,0,1,2,93,4,106,0,1,2,93,4,106,0, +1,2,93,4,106,0,1,2,93,4,106,0,1,2,98,4,106,0,1,2,93,4,106,0,1,2,93,4,106,0,1,2,104,4,176,0,1,7,124,7,30,0,1,7,146,0,12,0,226,1,198,1,204,1,210,1,216,1,222,1,228,1,234,1,240,1,246,1,252,2,2,2,8,2,14,2,20,2,26,2,32,2,38,2,44,2,50,2,56,2,62,2,68,2,74,2, +80,2,86,2,92,2,98,2,104,2,110,2,116,2,122,2,128,2,134,2,140,2,146,2,152,2,158,2,164,2,170,2,176,2,182,2,188,2,194,2,200,2,206,2,212,2,218,2,224,2,230,2,236,2,242,2,248,2,254,3,4,3,10,3,16,3,22,3,28,3,34,3,40,3,46,3,52,3,58,3,64,3,70,3,76,3,82,3,88,3, +94,3,100,3,106,3,112,3,118,3,124,3,130,3,136,3,142,3,148,3,154,3,160,3,166,3,172,3,178,3,184,3,190,3,196,3,202,3,208,3,214,3,220,3,226,3,232,3,238,3,244,3,250,4,0,4,6,4,12,4,18,4,24,4,30,4,36,4,42,4,48,4,54,4,60,4,66,4,72,4,78,4,84,4,90,4,96,4,102,4, +108,4,114,4,120,4,126,4,132,4,138,4,144,4,150,4,156,4,162,4,168,4,174,4,180,4,186,4,192,4,198,4,204,4,210,4,216,4,222,4,228,4,234,4,240,4,246,4,252,5,2,5,8,5,14,5,20,5,26,5,32,5,38,5,44,5,50,5,56,5,62,5,68,5,74,5,80,5,86,5,92,5,98,5,104,5,110,5,116,5, +122,5,128,5,134,5,140,5,146,5,152,5,158,5,164,5,170,5,176,5,182,5,188,5,194,5,200,5,206,5,212,5,218,5,224,5,230,5,236,5,242,5,248,5,254,6,4,6,10,6,16,6,22,6,28,6,34,6,40,6,46,6,52,6,58,6,64,6,70,6,76,6,82,6,88,6,94,6,100,6,106,6,112,6,118,6,124,6,130, +6,136,6,142,6,148,6,154,6,160,6,166,6,172,6,178,6,184,6,190,6,196,6,202,6,208,6,214,6,220,6,226,6,232,6,238,6,244,6,250,7,0,7,6,7,12,0,1,2,152,4,132,0,1,2,100,8,116,0,1,2,208,5,32,0,1,1,204,4,184,0,1,2,104,6,168,0,1,2,100,2,252,0,1,2,56,4,160,0,1,2,124, +3,212,0,1,2,36,4,160,0,1,1,244,4,124,0,1,2,4,4,96,0,1,2,4,5,72,0,1,1,208,4,76,0,1,1,192,5,68,0,1,2,4,2,252,0,1,1,152,4,32,0,1,2,92,3,240,0,1,1,220,5,116,0,1,1,64,3,184,0,1,1,52,4,72,0,1,0,232,6,184,0,1,0,236,6,212,0,1,1,156,5,40,0,1,1,124,5,244,0,1,2, +88,4,84,0,1,2,252,5,132,0,1,2,156,5,248,0,1,1,240,5,204,0,1,3,144,6,196,0,1,2,152,4,40,0,1,1,248,4,108,0,1,1,240,3,240,0,1,2,116,3,188,0,1,2,172,4,60,0,1,2,152,4,48,0,1,2,188,4,218,0,1,1,24,5,120,0,1,1,174,5,120,0,1,2,95,4,96,0,1,1,159,3,12,0,1,2,105, +3,232,0,1,2,70,3,232,0,1,2,87,3,232,0,1,2,87,3,232,0,1,2,133,3,232,0,1,2,64,3,232,0,1,2,84,3,232,0,1,2,84,3,232,0,1,2,91,3,232,0,1,2,58,3,232,0,1,2,66,3,232,0,1,2,96,3,232,0,1,2,130,4,76,0,1,2,76,4,76,0,1,2,91,5,19,0,1,2,90,5,20,0,1,2,91,4,157,0,1,2, +73,4,175,0,1,2,87,5,20,0,1,2,84,5,20,0,1,2,76,4,226,0,1,2,52,4,226,0,1,2,75,5,170,0,1,2,93,5,170,0,1,1,144,5,108,0,1,1,56,4,244,0,1,1,244,6,64,0,1,2,94,5,170,0,1,1,32,5,32,0,1,1,8,4,228,0,1,1,244,6,64,0,1,2,98,5,170,0,1,1,210,3,232,0,1,1,186,3,232,0, +1,1,172,3,232,0,1,2,88,3,232,0,1,1,178,3,232,0,1,1,166,3,232,0,1,1,132,3,232,0,1,2,88,3,232,0,1,1,178,3,232,0,1,1,150,3,231,0,1,1,184,3,232,0,1,2,88,3,232,0,1,1,198,3,232,0,1,1,194,3,232,0,1,1,196,3,232,0,1,2,88,3,232,0,1,2,111,4,77,0,1,2,188,4,226,0, +1,2,170,4,191,0,1,2,152,4,241,0,1,2,33,5,84,0,1,1,177,5,25,0,1,1,255,6,14,0,1,1,241,6,14,0,1,1,140,5,120,0,1,0,243,5,120,0,1,0,250,6,164,0,1,0,250,6,164,0,1,2,84,4,128,0,1,2,84,4,128,0,1,1,184,4,128,0,1,2,16,4,128,0,1,1,204,3,38,0,1,1,148,2,126,0,1,2, +79,3,232,0,1,2,91,3,232,0,1,2,176,4,184,0,1,2,12,8,216,0,1,2,88,8,224,0,1,2,140,5,80,0,1,2,88,5,68,0,1,1,128,4,216,0,1,1,28,3,244,0,1,2,44,5,97,0,1,2,68,5,102,0,1,2,92,6,216,0,1,2,80,6,232,0,1,2,104,3,60,0,1,2,16,2,232,0,1,2,12,3,200,0,1,2,92,3,156,0, +1,2,4,4,200,0,1,2,92,4,216,0,1,2,92,3,244,0,1,2,48,4,20,0,1,2,44,4,196,0,1,2,48,4,224,0,1,2,64,4,240,0,1,2,44,5,0,0,1,2,32,5,100,0,1,2,32,5,96,0,1,1,248,4,128,0,1,1,212,4,124,0,1,1,116,4,76,0,1,1,96,4,48,0,1,1,220,4,164,0,1,1,200,4,176,0,1,1,48,4,144, +0,1,1,128,4,132,0,1,1,220,5,64,0,1,1,216,5,92,0,1,1,32,4,224,0,1,1,24,4,220,0,1,2,12,4,172,0,1,2,4,4,184,0,1,2,8,5,84,0,1,2,20,5,96,0,1,2,64,3,20,0,1,1,180,3,16,0,1,1,148,4,76,0,1,1,56,4,136,0,1,2,52,4,15,0,1,1,206,3,183,0,1,2,53,3,222,0,1,1,243,3,197, +0,1,1,24,5,68,0,1,0,180,5,56,0,1,1,48,5,72,0,1,1,12,5,60,0,1,1,68,3,140,0,1,0,220,3,60,0,1,1,200,3,152,0,1,1,120,3,136,0,1,1,40,4,76,0,1,0,208,4,88,0,1,1,36,4,84,0,1,0,212,4,116,0,1,0,240,6,216,0,1,0,192,6,220,0,1,0,232,6,220,0,1,0,192,6,228,0,1,0,236, +6,244,0,1,0,208,6,228,0,1,0,240,6,232,0,1,0,200,6,224,0,1,1,132,5,48,0,1,1,168,4,84,0,1,1,196,5,76,0,1,2,104,4,132,0,1,1,132,6,48,0,1,1,216,5,112,0,1,1,128,6,76,0,1,2,104,5,60,0,1,2,248,5,112,0,1,2,248,4,248,0,1,1,172,5,184,0,1,2,108,5,36,0,1,2,100,5, +172,0,1,2,96,4,212,0,1,1,48,5,156,0,1,2,104,5,56,0,1,2,60,6,8,0,1,1,224,6,0,0,1,1,247,5,239,0,1,2,10,6,20,0,1,2,80,6,20,0,1,1,200,6,16,0,1,2,76,6,100,0,1,2,104,6,188,0,1,2,140,3,216,0,1,2,120,3,132,0,1,2,56,3,132,0,1,2,84,3,180,0,1,1,228,4,136,0,1,1, +135,3,82,0,1,2,32,4,109,0,1,2,36,4,118,0,1,1,234,3,136,0,1,2,50,3,122,0,1,1,175,4,96,0,1,1,238,3,28,0,1,2,131,3,77,0,1,2,59,3,41,0,1,1,252,3,82,0,1,1,166,2,68,0,1,2,5,3,104,0,1,1,112,2,95,0,1,2,41,3,73,0,1,2,32,3,82,0,1,2,124,3,212,0,1,2,111,4,126,0, +1,3,234,8,52,0,1,2,212,4,196,0,1,1,135,4,144,0,2,0,15,4,87,4,87,0,0,4,89,4,90,0,1,4,92,4,123,0,3,4,161,4,161,0,35,4,164,4,167,0,36,11,228,12,31,0,40,12,34,12,37,0,100,12,40,12,43,0,104,12,59,12,59,0,108,12,62,12,65,0,109,12,68,12,175,0,113,13,34,13,34, +0,221,13,39,13,39,0,222,13,41,13,41,0,223,13,43,13,44,0,224,0,1,0,9,4,124,4,125,4,127,4,128,4,130,4,131,4,132,4,133,4,135,0,9,0,0,0,38,0,0,0,44,0,0,0,50,0,0,0,56,0,0,0,62,0,0,0,68,0,0,0,74,0,0,0,80,0,0,0,86,0,1,2,93,4,106,0,1,2,93,4,106,0,1,2,93,4,106, +0,1,2,93,4,106,0,1,2,93,4,106,0,1,2,98,4,106,0,1,2,93,4,106,0,1,2,93,4,106,0,1,2,104,4,176,0,1,9,36,8,102,0,1,9,42,0,12,1,11,2,24,2,30,2,36,2,42,2,48,2,54,2,60,2,66,2,72,2,78,2,84,2,90,2,96,2,102,2,108,2,114,2,120,2,126,2,132,2,138,2,144,2,150,2,156, +2,162,2,168,2,174,2,180,2,186,2,192,2,198,2,204,2,210,2,216,2,222,2,228,2,234,2,240,2,246,2,252,3,2,3,8,3,14,3,20,3,26,3,32,3,38,3,44,3,50,3,56,3,62,3,68,3,74,3,80,3,86,3,92,3,98,3,104,3,110,3,116,3,122,3,128,3,134,3,140,3,146,3,152,3,158,3,164,3,170, +3,176,3,182,3,188,3,194,3,200,3,206,3,212,3,218,3,224,3,230,3,236,3,242,3,248,3,254,4,4,4,10,4,16,4,22,4,28,4,34,4,40,4,46,4,52,4,58,4,64,4,70,4,76,4,82,4,88,4,94,4,100,4,106,4,112,4,118,4,124,4,130,4,136,4,142,4,148,4,154,4,160,4,166,4,172,4,178,4,184, +4,190,4,196,4,202,4,208,4,214,4,220,4,226,4,232,4,238,4,244,4,250,5,0,5,6,5,12,5,18,5,24,5,30,5,36,5,42,5,48,5,54,5,60,5,66,5,72,5,78,5,84,5,90,5,96,5,102,5,108,5,114,5,120,5,126,5,132,5,138,5,144,5,150,5,156,5,162,5,168,5,174,5,180,5,186,5,192,5,198, +5,204,5,210,5,216,5,222,5,228,5,234,5,240,5,246,5,252,6,2,6,8,6,14,6,20,6,26,6,32,6,38,6,44,6,50,6,56,6,62,6,68,6,74,6,80,6,86,6,92,6,98,6,104,6,110,6,116,6,122,6,128,6,134,6,140,6,146,6,152,6,158,6,164,6,170,6,176,6,182,6,188,6,194,6,200,6,206,6,212, +6,218,6,224,6,230,6,236,6,242,6,248,6,254,7,4,7,10,7,16,7,22,7,28,7,34,7,40,7,46,7,52,7,58,7,64,7,70,7,76,7,82,7,88,7,94,7,100,7,106,7,112,7,118,7,124,7,130,7,136,7,142,7,148,7,154,7,160,7,166,7,172,7,178,7,184,7,190,7,196,7,202,7,208,7,214,7,220,7,226, +7,232,7,238,7,244,7,250,8,0,8,6,8,12,8,18,8,24,8,30,8,36,8,42,8,48,8,54,8,60,8,66,8,72,8,78,8,84,0,1,4,68,0,0,0,1,2,104,0,0,0,1,2,179,0,0,0,1,1,120,0,0,0,1,2,122,0,0,0,1,1,79,0,0,0,1,2,154,0,0,0,1,3,226,0,0,0,1,2,104,0,0,0,1,2,154,0,0,0,1,4,68,0,0,0, +1,2,154,0,0,0,1,4,28,0,0,0,1,3,228,0,0,0,1,2,104,0,0,0,1,1,42,0,0,0,1,2,104,0,0,0,1,4,68,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,3,147,0,0,0,1,4,68,0,0,0,1,2,104,0,0,0,1,2,154,0,0,0,1,3,198,0,0,0,1,2,104,0,0,0,1,2,208,0,0,0,1, +2,104,0,0,0,1,2,118,0,0,0,1,2,104,0,0,0,1,2,104,254,86,0,1,3,190,0,0,0,1,2,104,0,0,0,1,1,185,254,89,0,1,4,68,0,0,0,1,3,120,0,0,0,1,4,27,0,0,0,1,3,190,0,0,0,1,2,104,0,0,0,1,1,26,254,86,0,1,3,194,254,86,0,1,1,198,0,0,0,1,2,104,0,0,0,1,3,120,0,0,0,1,2,104, +0,0,0,1,2,104,0,0,0,1,3,115,0,0,0,1,4,68,0,0,0,1,1,26,254,86,0,1,2,104,0,0,0,1,4,68,0,0,0,1,4,68,0,0,0,1,4,68,0,0,0,1,4,68,0,0,0,1,4,68,0,0,0,1,4,68,0,0,0,1,2,122,0,0,0,1,2,122,0,0,0,1,2,122,0,0,0,1,2,122,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0, +0,1,2,104,0,0,0,1,2,54,0,0,0,1,3,228,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,1,52,0,0,0,1,2,54,0,0,0,1,3,198,0,0,0,1,3,198,0,0,0, +1,3,198,0,0,0,1,3,198,0,0,0,1,3,198,0,0,0,1,3,198,0,0,0,1,2,118,0,0,0,1,2,118,0,0,0,1,2,118,0,0,0,1,2,118,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,3,190,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0, +0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,1,26,254,86,0,1,1,26,254,86,0,1,1,26,254,86,0,1,4,68,0,0,0,1,4,68,0,0,0,1,3,198,0,0,0,1,2,179,0,0,0,1,2,179,0,0,0,1,2,208,0,0,0,1,2,179,0,0,0,1,2,208,0,0,0,1,2,179, +0,0,0,1,2,208,0,0,0,1,2,54,0,0,0,1,2,104,0,0,0,1,2,54,0,0,0,1,2,104,0,0,0,1,2,122,0,0,0,1,2,118,0,0,0,1,2,122,0,0,0,1,2,118,0,0,0,1,2,122,0,0,0,1,2,118,0,0,0,1,2,122,0,0,0,1,2,118,0,0,0,1,2,154,0,0,0,1,2,104,254,86,0,1,2,154,0,0,0,1,2,104,254,86,0,1, +2,154,0,0,0,1,2,104,254,86,0,1,2,104,254,86,0,1,3,226,0,0,0,1,3,190,0,0,0,1,3,226,0,0,0,1,3,190,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,154,0,0,0,1,1,185,254,89,0,1,4,68, +0,0,0,1,2,154,0,0,0,1,3,120,0,0,0,1,2,154,0,0,0,1,3,120,0,0,0,1,2,154,0,0,0,1,3,120,0,0,0,1,2,154,0,0,0,1,3,120,0,0,0,1,3,228,0,0,0,1,3,190,0,0,0,1,3,228,0,0,0,1,3,190,0,0,0,1,4,57,0,0,0,1,2,104,254,86,0,1,2,104,254,86,0,1,2,104,0,0,0,1,2,104,0,0,0,1, +2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,4,68,0,0,0,1,1,198,0,0,0,1,4,68,0,0,0,1,1,198,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,3,120,0,0,0,1,2,104,0,0,0,1,3,120,0,0,0,1, +2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,3,147,0,0,0,1,3,115,0,0,0,1,2,104,0,0,0,1,1,26,254,86,0,1,2,104,0,0,0,1,2,154,0,0,0,1,2,104,0,0,0,1,2,154,0,0, +0,1,2,104,0,0,0,1,2,154,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,10,0,0,0,1,2,179,0,0,0,1,2,208,0,0,0,1,2,54,0,0,0,1,2,54,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,254,86, +0,1,2,86,0,0,0,1,2,104,0,0,0,1,2,179,0,0,0,1,1,34,254,86,0,1,1,104,254,86,0,1,2,154,0,0,0,1,2,104,254,86,0,1,3,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,4,68,0,0,0,1,4,68,0,0,0,1,3,120,0,0,0,1,4,8,0,0,0,1,4,28,0,0,0,1,3,228,0,0,0,1,3,190,254,86,0,1,2,104, +0,0,0,1,1,249,0,0,0,1,1,255,0,0,0,1,2,104,0,0,0,1,4,88,254,86,0,1,1,210,0,0,0,1,1,26,254,86,0,1,4,106,254,248,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,4,68,0,0,0,1,1,198,0,0,0,1,2,154,0,0,0,1,4,68,0,0,0,1,2,164,254,86, +0,1,2,104,0,0,0,1,2,104,254,86,0,1,2,154,254,86,0,1,2,104,254,86,0,1,2,104,254,86,0,1,4,73,0,0,0,1,3,86,2,156,0,2,0,31,0,36,0,61,0,0,0,68,0,93,0,26,0,130,0,135,0,52,0,138,0,152,0,58,0,154,0,167,0,73,0,170,0,184,0,87,0,186,0,194,0,102,0,196,0,197,0,111, +0,200,0,200,0,113,0,202,0,217,0,114,0,220,0,227,0,130,0,229,0,239,0,138,0,242,0,243,0,149,0,246,0,247,0,151,0,250,0,252,0,153,0,255,1,6,0,156,1,9,1,19,0,164,1,22,1,23,0,175,1,26,1,31,0,177,1,34,1,35,0,183,1,38,1,51,0,185,1,54,1,107,0,199,1,241,1,242, +0,253,1,244,1,245,0,255,2,212,2,212,1,1,11,167,11,167,1,2,11,169,11,169,1,3,11,176,11,176,1,4,11,179,11,180,1,5,11,212,11,213,1,7,11,222,11,223,1,9,0,1,0,1,2,175,0,1,0,0,0,6,0,1,2,124,0,0,0,1,24,34,23,58,0,2,24,80,0,12,1,189,6,246,6,252,7,2,7,8,7,14, +7,20,7,26,7,32,7,38,7,44,7,50,7,56,7,62,7,68,7,74,7,80,7,86,7,92,7,98,7,104,7,110,7,116,7,122,7,128,7,134,7,140,7,146,7,152,7,158,7,164,7,170,7,176,7,182,7,188,7,194,7,200,7,206,7,212,7,218,7,224,7,230,7,236,7,242,7,248,7,254,8,4,8,10,8,16,8,22,8,28, +8,34,8,40,8,46,8,52,8,58,8,64,8,70,8,76,8,82,8,88,8,94,8,100,8,106,8,112,8,118,8,124,8,130,8,136,0,0,8,142,0,0,8,148,8,154,8,160,8,166,8,172,8,178,8,184,8,190,8,196,8,202,8,208,8,214,8,220,8,226,8,232,8,238,8,244,8,250,9,0,9,6,9,12,9,18,9,24,9,30,9,36, +9,42,9,48,9,54,9,60,9,66,9,72,9,78,9,84,0,0,9,90,0,0,9,96,0,0,9,102,0,0,9,108,0,0,9,114,0,0,9,120,9,126,9,132,9,138,0,0,0,0,9,144,0,0,9,150,0,0,9,156,0,0,9,162,0,0,9,168,0,0,9,174,0,0,9,180,0,0,9,186,9,192,9,198,0,0,9,204,0,0,9,210,0,0,9,216,0,0,9,222, +0,0,9,228,0,0,9,234,9,240,9,246,0,0,9,252,0,0,10,2,0,0,10,8,0,0,10,14,0,0,10,20,10,26,10,32,10,38,10,44,0,0,10,50,0,0,10,56,0,0,10,62,0,0,10,68,0,0,10,74,0,0,10,80,10,86,10,92,10,98,0,0,0,0,10,104,0,0,10,110,0,0,10,116,0,0,10,122,0,0,10,128,0,0,10,134, +0,0,10,140,0,0,10,146,0,0,10,152,0,0,10,158,0,0,10,164,0,0,10,170,0,0,10,176,0,0,10,182,0,0,10,188,10,194,10,200,0,0,10,206,0,0,10,212,0,0,10,218,0,0,10,224,0,0,10,230,10,236,10,242,0,0,10,248,0,0,10,254,0,0,11,4,0,0,11,10,11,16,0,0,11,22,0,0,0,0,11, +28,0,0,11,34,0,0,11,40,0,0,11,46,0,0,11,52,0,0,11,58,0,0,11,64,0,0,11,70,0,0,11,76,11,82,11,88,11,94,11,100,0,0,11,106,0,0,11,112,0,0,11,118,0,0,11,124,0,0,11,130,0,0,11,136,11,142,0,0,11,148,0,0,0,0,11,154,0,0,11,160,0,0,11,166,0,0,11,172,0,0,11,178, +0,0,11,184,0,0,11,190,0,0,11,196,11,202,0,0,0,0,11,208,0,0,11,214,0,0,11,220,11,226,11,232,11,238,11,244,0,0,11,250,0,0,12,0,0,0,12,6,0,0,12,12,0,0,12,18,0,0,12,24,12,30,0,0,0,0,12,36,12,42,12,48,0,0,12,54,0,0,12,60,12,66,0,0,12,72,0,0,12,78,12,84,0, +0,12,90,0,0,12,96,12,102,0,0,12,108,0,0,0,0,12,114,0,0,12,120,12,126,12,132,12,138,12,144,12,150,12,156,12,162,12,168,0,0,12,174,0,0,12,180,12,186,0,0,12,192,0,0,0,0,12,198,0,0,12,204,0,0,12,210,12,216,12,222,12,228,12,234,0,0,12,240,0,0,12,246,0,0,12, +252,0,0,13,2,0,0,13,8,0,0,13,14,13,20,13,26,13,32,13,38,0,0,13,44,0,0,13,50,13,56,0,0,13,62,0,0,0,0,13,68,13,74,13,80,0,0,13,86,0,0,13,92,0,0,13,98,0,0,13,104,13,110,0,0,13,116,0,0,0,0,13,122,0,0,13,128,13,134,0,0,13,140,0,0,0,0,13,146,0,0,13,152,13, +158,13,164,13,170,13,176,0,0,13,182,0,0,13,188,0,0,13,194,0,0,13,200,0,0,13,206,0,0,13,212,0,0,13,218,0,0,13,224,0,0,13,230,0,0,13,236,13,242,0,0,13,248,0,0,0,0,13,254,0,0,14,4,0,0,14,10,0,0,14,16,0,0,14,22,0,0,14,28,0,0,14,34,0,0,14,40,0,0,14,46,0,0, +14,52,0,0,14,58,14,64,14,70,14,76,14,82,14,88,14,94,14,100,14,106,14,112,14,118,14,124,14,130,14,136,14,142,14,148,14,154,14,160,14,166,14,172,14,178,14,184,14,190,14,196,14,202,14,208,14,214,14,220,14,226,14,232,14,238,14,244,14,250,15,0,15,6,15,12, +15,18,15,24,15,30,15,36,15,42,15,48,15,54,15,60,15,66,15,72,15,78,15,84,15,90,15,96,15,102,15,108,15,114,15,120,15,126,15,132,15,138,15,144,15,150,15,156,15,162,15,168,15,174,15,180,15,186,15,192,15,198,15,204,15,210,15,216,15,222,15,228,15,234,15,240, +15,246,15,252,16,2,16,8,16,14,16,20,16,26,16,32,16,38,16,44,16,50,16,56,16,62,16,68,16,74,16,80,16,86,16,92,16,98,16,104,16,110,16,116,16,122,16,128,16,134,16,140,16,146,16,152,16,158,16,164,16,170,16,176,16,182,16,188,16,194,16,200,16,206,16,212,16, +218,16,224,16,230,16,236,16,242,16,248,16,254,17,4,17,10,17,16,17,22,17,28,17,34,17,40,17,46,17,52,17,58,17,64,17,70,17,76,17,82,17,88,17,94,17,100,17,106,17,112,17,118,17,124,17,130,17,136,17,142,17,148,17,154,17,160,17,166,17,172,17,178,17,184,17,190, +17,196,17,202,17,208,17,214,17,220,17,226,17,232,17,238,17,244,17,250,18,0,18,6,18,12,18,18,18,24,18,30,18,36,18,42,18,48,18,54,18,60,18,66,18,72,18,78,18,84,18,90,18,96,18,102,18,108,18,114,18,120,18,126,18,132,18,138,18,144,18,150,18,156,18,162,18, +168,18,174,18,180,18,186,18,192,18,198,18,204,18,210,18,216,18,222,18,228,18,234,18,240,18,246,18,252,19,2,19,8,19,14,19,20,19,26,19,32,19,38,19,44,19,50,19,56,19,62,19,68,19,74,19,80,19,86,19,92,19,98,19,104,19,110,19,116,19,122,19,128,19,134,19,140, +19,146,19,152,19,158,19,164,19,170,19,176,19,182,19,188,19,194,19,200,19,206,19,212,19,218,19,224,19,230,19,236,19,242,19,248,19,254,20,4,20,10,20,16,20,22,20,28,20,34,20,40,20,46,20,52,20,58,20,64,20,70,20,76,0,0,20,82,0,0,20,88,0,0,20,94,0,0,20,100, +0,0,20,106,0,0,20,112,0,0,20,118,0,0,20,124,0,0,20,130,0,0,20,136,0,0,20,142,0,0,20,148,0,0,20,154,0,0,20,160,0,0,20,166,0,0,20,172,0,0,20,178,0,0,20,184,0,0,20,190,0,0,20,196,0,0,20,202,0,0,20,208,0,0,20,214,0,0,20,220,0,0,20,226,0,0,20,232,0,0,20,238, +0,0,20,244,0,0,20,250,0,0,21,0,0,0,21,6,0,0,21,12,0,0,21,18,21,24,21,30,21,36,21,42,21,48,21,54,21,60,21,66,21,72,21,78,21,84,21,90,21,96,21,102,21,108,21,114,21,120,21,126,21,132,21,138,21,144,21,150,21,156,21,162,21,168,21,174,21,180,21,186,21,192, +21,198,21,204,21,210,21,216,21,222,21,228,21,234,21,240,21,246,21,252,22,2,22,8,22,14,22,20,22,26,0,0,0,0,22,32,0,0,22,38,22,44,22,50,22,56,22,62,22,68,22,74,22,80,22,86,22,92,22,98,22,104,22,110,22,116,22,122,22,128,22,134,22,140,22,146,22,152,22,158, +22,164,22,170,22,176,22,182,22,188,22,194,22,200,22,206,22,212,22,218,22,224,22,230,22,236,22,242,22,248,22,254,23,4,23,10,23,16,23,22,23,28,23,34,23,40,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,179,5,213,0,1,2,179,0,0,0,1, +2,54,5,213,0,1,2,54,0,0,0,1,2,122,5,213,0,1,2,122,0,0,0,1,2,158,5,213,0,1,2,158,0,0,0,1,2,154,5,213,0,1,2,154,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,154,5,213,0,1,2,154,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,154,5,213, +0,1,2,154,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,54,5,213,0,1,2,54,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0, +0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,154,5,213,0,1,2,154,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,179, +4,96,0,1,2,179,0,0,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,118,4,96,0,1,2,118,0,0,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,254,86,0,1,2,154,6,20,0,1,2,154,0,0,0,1,2,50,6,20,0,1,2,50, +0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,104, +4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0, +0,1,2,122,5,213,0,1,2,122,0,0,0,1,2,179,5,213,0,1,2,122,0,0,0,1,2,122,0,0,0,1,2,122,0,0,0,1,2,122,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,54,5,213,0,1,2,54,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104, +0,0,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,54,5,213,0,1,2,54,0,0,0,1,2,54,5,213,0,1,2,54,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2, +104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,179,4,96,0,1,2,118,0,0,0,1,2,118,0,0,0,1,2,118,0,0,0,1,2,118,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0, +1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,254,86,0,1,2,104,6,20,0,1,2,104,254,86,0,1,2,104,254,86,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,4,96,0,1,2,179,0,0, +0,1,2,179,0,0,0,1,2,179,0,0,0,1,2,179,0,0,0,1,2,179,0,0,0,1,2,179,0,0,0,1,2,179,0,0,0,1,2,54,0,0,0,1,2,104,0,0,0,1,2,54,5,213,0,1,2,54,0,0,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,122,0,0,0,1,2,118,0,0,0,1,2,122,0,0,0,1,2,118,0,0,0,1,2,122,0,0,0,1,2,118,0, +0,0,1,2,122,5,213,0,1,2,118,4,96,0,1,2,122,0,0,0,1,2,118,0,0,0,1,2,154,0,0,0,1,2,104,254,86,0,1,2,154,0,0,0,1,2,104,254,86,0,1,2,154,0,0,0,1,2,104,254,86,0,1,2,154,5,213,0,1,2,104,254,86,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2, +104,6,20,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,154,0,0,0,1,2,104,254,86,0,1,2,104,5,213,0,1,2,154,6,20,0,1,2,154,4,96,0,1,2,154, +0,0,0,1,2,154,0,0,0,1,2,50,0,0,0,1,2,154,5,213,0,1,2,50,6,20,0,1,2,154,0,0,0,1,2,50,0,0,0,1,2,154,5,213,0,1,2,154,0,0,0,1,2,50,6,20,0,1,2,50,0,0,0,1,2,154,5,213,0,1,2,154,0,0,0,1,2,50,6,20,0,1,2,50,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,5,213,0,1, +2,104,4,96,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,227,0,0,0,1,2,104,5,213,0,1,2,104,254,86,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,4,96,0,1, +2,104,0,0,0,1,2,54,0,0,0,1,2,104,0,0,0,1,2,54,5,213,0,1,2,104,4,96,0,1,2,54,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104, +6,20,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,5,213,0, +1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,254,86,0,1,2,104,0,0,0,1,2,154,0,0,0,1,2,104,0,0,0,1,2,154,0,0,0,1,2,104,0,0,0,1,2,154,0,0,0,1,2,104,0,0,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2, +104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,10,5,213,0,1,2,10,0,0,0,1,2,179,5,213,0,1,2,179,0,0,0,1,2,179,4,96,0,1,2,179,0,0,0,1,2,54,5,213,0,1,2,54,0,0,0,1,2,54, +5,213,0,1,2,54,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,86,5,213,0,1,2,86,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,179,5,213,0,1,2,179,0,0,0,1,3,2,5,213,0,1,3,2,254,86,0,1,2,104,6,20,0,1,2,104, +254,86,0,1,2,154,5,213,0,1,2,154,0,0,0,1,2,104,5,213,0,1,2,104,254,86,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,154,6,20,0,1,2,154,0,0,0,1,2,50,6,20,0,1,2,50,0,0,0,1,2, +104,6,20,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,254,86,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,104,5,213,0,1,2,104,0,0,0,1,1,249,5,213,0,1,1,249,0,0,0,1,1,255,4,96,0,1,1,255,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,4,96, +0,1,2,104,254,86,0,1,2,236,5,213,0,1,2,236,0,0,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,54,5,213,0,1,2,54,254,86,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2, +104,254,86,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,0,0,0,1,2,54,5,213,0,1,2,54,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,140,6,20,0,1,2,140,0,0,0,1,2, +41,4,96,0,1,2,41,0,0,0,1,2,179,4,96,0,1,2,179,0,0,0,1,2,89,6,20,0,1,2,89,0,0,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,118,4,96,0,1,2,118,0,0,0,1,2,118,4,96,0,1,2,118,0,0,0,1,1,154,4,96,0,1,1,154,0,0,0,1,2,118,4,96,0,1,2,118,0,0,0,1,2,90,4,96,0,1,2,90,0,0,0, +1,1,114,4,96,0,1,1,114,0,0,0,1,2,118,4,96,0,1,2,118,0,0,0,1,2,177,4,96,0,1,2,177,254,86,0,1,2,62,6,20,0,1,2,62,254,86,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,149,4,96,0,1,2,149,0,0,0,1,2,110,4,96,0,1,2,110,254,86,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104, +4,96,0,1,2,104,254,86,0,1,2,111,6,20,0,1,2,111,0,0,0,1,2,111,6,20,0,1,2,111,254,86,0,1,2,68,4,96,0,1,2,68,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,56,6,20,0,1,2,56,0,0,0,1,2,80,6,20,0,1,2,80,0,0,0,1,2,62,6,20,0,1,2,62,254,86,0,1,2,104,4,96,0,1,2,104,0, +0,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,182,4,96,0,1,2,182,254,86,0,1,1,252,4,102,0,1,2,38,254,86,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1, +2,104,6,20,0,1,2,104,254,86,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,54,4,96,0,1,2,54,254,86,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,99,4,96,0,1,2,99,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,0,4,96,0, +1,2,0,0,0,0,1,2,0,4,96,0,1,2,0,0,0,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,115,6,20,0,1,2,115,254,86,0,1,2,115,6,20,0,1,2,115,254,86,0,1,2,120,4,96,0,1,2,120,254,86,0,1,2,115,6,20,0,1,2,115,254,86,0,1,2,164,4,96,0,1,2,164,254,86,0,1,2,104,6,20,0,1,2,104, +254,86,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,6,20,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,28,4,96,0,1,2,28,254,86,0,1,2,104, +4,96,0,1,2,104,255,142,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,36,6,20,0,1,2,36,0,0,0,1,2,170,6,20,0,1,2,170,0,0,0,1,2,36,6,20,0,1,2,36,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,32,4,96,0,1,2,32,0,0,0,1,2,62,4,96,0,1,2,62,0, +0,0,1,2,26,6,20,0,1,2,26,0,0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,254,86,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,6,20,0,1,2,104,254,86,0,1,2,36,6,20,0,1,2,36,0,0,0,1,2,170,6,20,0,1,2,170,0,0,0,1,2,154,5,213,0,1,2,154,0,0,0,1,2,104,4,96, +0,1,2,104,6,20,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,118,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,179,4,96,0,1,2,104, +4,96,0,1,2,104,4,96,0,1,2,104,6,20,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,53,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,179,4,96,0,1,2,104,4,96,0,1,3,39,5,240,0,1,3, +39,0,0,0,1,2,125,4,123,0,1,2,125,0,0,0,1,2,104,5,224,0,1,2,104,2,156,0,1,2,82,5,224,0,1,2,82,2,156,0,1,2,69,5,224,0,1,2,69,2,156,0,1,2,94,5,224,0,1,2,94,2,156,0,1,2,114,5,224,0,1,2,114,2,156,0,1,2,144,5,224,0,1,2,144,2,156,0,1,2,104,5,224,0,1,2,104,2, +156,0,1,2,104,5,224,0,1,2,104,2,156,0,1,2,188,5,224,0,1,2,188,2,156,0,1,2,63,5,224,0,1,2,63,2,156,0,1,2,97,5,224,0,1,2,97,2,156,0,1,2,105,5,224,0,1,2,105,2,156,0,1,2,104,5,224,0,1,2,104,2,156,0,1,2,104,5,224,0,1,2,104,2,156,0,1,2,104,5,224,0,1,2,104, +2,156,0,1,2,71,5,224,0,1,2,71,2,156,0,1,2,27,5,224,0,1,2,27,2,156,0,1,2,104,5,224,0,1,2,104,2,156,0,1,2,104,5,224,0,1,2,104,2,156,0,1,2,104,5,224,0,1,2,104,2,156,0,1,2,54,5,213,0,1,2,104,0,0,0,1,2,92,2,156,0,1,2,97,5,240,0,1,2,97,0,0,0,1,2,100,5,226, +0,1,2,100,0,0,0,1,2,53,5,240,0,1,2,53,0,0,0,1,2,103,5,240,0,1,3,39,0,0,0,1,2,101,5,226,0,1,2,101,0,0,0,1,2,96,5,226,0,1,2,96,0,0,0,1,2,54,5,213,0,1,2,54,254,76,0,1,2,104,5,213,0,1,2,164,254,86,0,1,2,105,5,213,0,1,2,105,0,0,0,1,2,104,6,20,0,1,2,104,0, +0,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,5,213,0,1,2,104,254,86,0,1,2,154,5,213,0,1,2,154,254,86,0,1,2,104,5,213,0,1,2,104,254,86,0,1,2,104,6,20,0,1,2,104,254,86,0,1,2,105,6,20,0,1,2,105,254,86,0,1,2,49,5,213,0,1,2,49,0,0,0,1,2,31,4,96,0,1,2,31,0,0,0, +1,3,0,5,213,0,1,3,0,0,0,0,1,2,104,5,224,0,1,2,104,2,156,0,1,2,107,5,15,0,1,2,107,2,156,0,1,2,104,5,213,0,2,0,38,0,36,0,61,0,0,0,68,0,93,0,26,0,130,0,152,0,52,0,154,0,184,0,75,0,186,0,194,0,106,0,196,0,200,0,115,0,202,0,240,0,120,0,242,0,243,0,159,0,246, +1,107,0,161,1,209,1,209,1,23,1,230,1,230,1,24,1,241,1,242,1,25,1,244,2,13,1,27,2,15,2,19,1,53,2,21,2,60,1,58,2,62,2,66,1,98,2,68,2,72,1,103,2,212,2,212,1,108,3,111,3,119,1,109,3,121,3,142,1,118,3,147,3,148,1,140,3,161,3,162,1,142,5,23,5,23,1,144,5,25, +5,43,1,145,5,129,5,129,1,164,5,184,5,184,1,165,7,71,7,71,1,166,7,140,7,140,1,167,7,143,7,143,1,168,7,146,7,148,1,169,7,150,7,150,1,172,11,167,11,167,1,173,11,169,11,170,1,174,11,175,11,176,1,176,11,179,11,180,1,178,11,212,11,213,1,180,11,219,11,224,1, +182,13,31,13,31,1,188,0,2,0,7,2,136,2,153,0,0,2,155,2,161,0,18,2,164,2,168,0,25,2,171,2,174,0,30,2,177,2,185,0,34,2,193,2,198,0,43,2,200,2,200,0,49,0,50,0,0,0,202,0,0,0,208,0,0,0,214,0,0,0,220,0,0,0,226,0,0,0,232,0,0,0,238,0,0,0,244,0,0,0,250,0,0,1,0, +0,0,1,6,0,0,1,12,0,0,1,18,0,0,1,24,0,0,1,30,0,0,1,36,0,0,1,42,0,0,1,48,0,0,1,54,0,0,1,60,0,0,1,66,0,1,1,72,0,1,1,78,0,1,1,84,0,1,1,90,0,1,1,96,0,1,1,102,0,1,1,108,0,1,1,114,0,1,1,120,0,1,1,126,0,1,1,132,0,1,1,138,0,1,1,144,0,1,1,150,0,1,1,156,0,1,1,162, +0,1,1,168,0,1,1,174,0,1,1,180,0,1,1,186,0,1,1,192,0,1,1,198,0,1,1,204,0,1,1,210,0,1,1,216,0,1,1,222,0,0,1,228,0,0,1,234,0,0,1,240,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96, +0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0, +0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0, +0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,0,0,0,1,2,104,4,96,0,1,2,104,4,96,0,1,2,104,4,96,0,1,0,8,0,4,251,47,0,2,0,6,2,136,2,153,0,0,2,155,2,161,0,18,2,164,2,168,0,25,2,171,2,185,0,30,2,193,2,198,0,45,2,200,2,200,0,51,0,1,1,200,1,190,0,2, +1,216,0,12,0,27,0,110,0,116,0,122,0,128,0,134,0,140,0,146,0,152,0,158,0,164,0,170,0,176,0,182,0,188,0,194,0,200,0,206,0,212,0,218,0,224,0,230,0,236,0,242,0,248,0,254,1,4,1,10,1,16,1,22,1,28,1,34,1,40,1,46,1,52,1,58,1,64,1,70,1,76,1,82,1,88,1,94,1,100, +1,106,1,112,1,118,1,124,1,130,1,136,1,142,1,148,1,154,1,160,1,166,1,172,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,254,20,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,254,20,0,1,4,209, +4,160,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,254,20,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,210,6,16,0, +1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,210,6,16,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,210,6,16,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,209,6,16,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0, +1,4,209,4,160,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,209,4,160,0,1,4,209,0,0,0,1,4,209,4,160,0,2,0,1,4,179,4,205,0,0,0,2,0,2,4,208,4,208,0,0,4,211,4,224,0,1,0,15,0,1,0,62,0,1,0,68,0,1,0,74,0,1,0,80,0,1,0,86,0, +0,0,92,0,0,0,98,0,1,0,104,0,0,0,110,0,1,0,116,0,1,0,122,0,1,0,128,0,1,0,134,0,1,0,140,0,1,0,146,0,1,255,247,4,116,0,1,4,209,4,119,0,1,4,209,4,119,0,1,4,209,4,119,0,1,4,209,4,119,0,1,4,209,0,0,0,1,4,209,0,0,0,1,4,209,4,116,0,1,4,209,0,0,0,1,4,209,4,96, +0,1,4,209,4,126,0,1,4,209,4,126,0,1,4,209,4,96,0,1,4,209,4,126,0,1,4,209,4,96,0,1,0,8,0,4,251,47,0,2,0,2,4,208,4,208,0,0,4,211,4,224,0,1,0,0,0,1,0,0,0,10,0,242,1,108,0,6,68,70,76,84,0,38,97,114,97,98,0,50,99,121,114,108,0,70,103,114,101,107,0,98,108, +97,111,32,0,110,108,97,116,110,0,120,0,4,0,0,0,0,255,255,0,1,0,0,0,4,0,0,0,0,255,255,0,5,0,3,0,4,0,5,0,8,0,9,0,10,0,1,83,82,66,32,0,18,0,0,255,255,0,1,0,1,0,0,255,255,0,2,0,1,0,6,0,4,0,0,0,0,255,255,0,1,0,1,0,4,0,0,0,0,255,255,0,0,0,70,0,11,67,65,84, +32,0,82,69,83,80,32,0,82,71,65,76,32,0,82,73,83,77,32,0,90,75,83,77,32,0,90,76,83,77,32,0,90,77,79,76,32,0,102,78,83,77,32,0,90,82,79,77,32,0,102,83,75,83,32,0,90,83,83,77,32,0,90,0,0,255,255,0,3,0,0,0,1,0,2,0,0,255,255,0,1,0,0,0,0,255,255,0,3,0,1,0, +2,0,7,0,0,255,255,0,2,0,1,0,2,0,10,99,97,115,101,0,62,99,99,109,112,0,68,100,108,105,103,0,74,102,105,110,97,0,80,105,110,105,116,0,86,108,105,103,97,0,92,108,111,99,108,0,98,108,111,99,108,0,104,109,101,100,105,0,110,114,108,105,103,0,116,0,0,0,1,0, +10,0,0,0,1,0,1,0,0,0,1,0,8,0,0,0,1,0,3,0,0,0,1,0,5,0,0,0,1,0,7,0,0,0,1,0,2,0,0,0,1,0,0,0,0,0,1,0,4,0,0,0,1,0,6,0,11,0,24,0,32,0,40,0,48,0,56,0,64,0,72,0,80,0,88,0,96,0,104,0,1,0,0,0,1,0,88,0,6,0,0,0,1,0,92,0,1,0,0,0,1,0,228,0,1,0,9,0,1,0,232,0,1,0,9, +0,1,1,108,0,1,0,9,0,1,1,236,0,4,0,9,0,1,2,108,0,4,0,9,0,1,2,138,0,4,0,0,0,1,2,200,0,1,0,0,0,1,2,224,0,1,0,0,0,1,2,234,0,1,0,6,12,19,0,1,0,1,1,12,0,2,0,20,0,28,0,36,0,36,0,4,0,0,0,88,0,0,0,0,0,1,0,2,0,76,0,77,0,1,0,0,0,1,0,0,0,2,0,8,0,76,0,77,0,1,2,136, +2,157,0,2,2,158,2,161,0,3,2,164,2,168,0,3,2,171,2,187,0,3,2,193,2,196,0,3,2,197,2,200,0,2,2,203,2,203,0,2,0,3,0,8,0,22,0,38,0,0,0,1,0,1,0,2,0,1,0,0,0,9,0,0,0,1,0,2,0,3,0,2,0,1,0,0,0,9,0,0,0,1,0,3,0,3,0,3,0,2,0,1,0,0,0,9,0,1,0,6,8,113,0,1,0,1,3,112,0, +2,0,112,0,53,12,61,12,63,12,65,12,67,12,69,12,73,12,75,12,79,12,81,12,85,12,89,12,93,12,97,12,101,12,103,12,105,12,107,12,109,12,113,12,117,12,121,12,125,12,129,12,133,12,137,12,141,12,145,12,149,12,153,12,157,12,161,12,165,12,169,12,171,12,173,11,249, +11,241,11,229,11,233,11,245,11,237,12,9,12,5,12,13,12,17,12,23,12,21,11,253,12,25,12,29,12,35,12,41,12,33,0,2,0,4,4,88,4,112,0,0,4,114,4,123,0,25,4,151,4,167,0,35,13,42,13,42,0,52,0,2,0,84,0,39,12,71,12,77,12,83,12,87,12,91,12,95,12,99,12,111,12,115, +12,119,12,123,12,127,12,131,12,135,12,139,12,143,12,147,12,151,12,155,12,159,12,163,12,167,12,39,12,175,11,251,11,243,11,231,11,235,11,247,11,239,12,11,12,7,12,15,12,19,11,255,12,27,12,31,12,37,12,43,0,2,0,8,4,92,4,92,0,0,4,94,4,94,0,1,4,96,4,100,0,2, +4,105,4,112,0,7,4,114,4,120,0,15,4,122,4,123,0,22,4,151,4,160,0,24,4,163,4,167,0,34,0,2,0,84,0,39,12,70,12,76,12,82,12,86,12,90,12,94,12,98,12,110,12,114,12,118,12,122,12,126,12,130,12,134,12,138,12,142,12,146,12,150,12,154,12,158,12,162,12,166,12,38, +12,174,11,250,11,242,11,230,11,234,11,246,11,238,12,10,12,6,12,14,12,18,11,254,12,26,12,30,12,36,12,42,0,2,0,8,4,92,4,92,0,0,4,94,4,94,0,1,4,96,4,100,0,2,4,105,4,112,0,7,4,114,4,120,0,15,4,122,4,123,0,22,4,151,4,160,0,24,4,163,4,167,0,34,0,1,0,30,0,2, +0,10,0,20,0,1,0,4,12,182,0,2,12,73,0,1,0,4,12,183,0,2,12,73,0,1,0,2,12,154,12,155,0,1,0,62,0,2,0,10,0,36,0,3,0,8,0,14,0,20,12,180,0,2,12,67,12,178,0,2,12,63,12,176,0,2,12,61,0,3,0,8,0,14,0,20,12,181,0,2,12,67,12,179,0,2,12,63,12,177,0,2,12,61,0,1,0,2, +12,154,12,155,0,1,0,26,0,1,0,8,0,2,0,6,0,12,11,227,0,2,0,79,11,226,0,2,0,76,0,1,0,1,0,73,0,2,0,10,0,2,0,243,1,230,0,1,0,2,0,76,0,77,0,2,0,12,0,3,13,46,13,47,13,48,0,1,0,3,0,99,0,129,11,181,0,1,4,209,1,144,0,5,0,0,5,51,5,153,0,0,1,30,5,51,5,153,0,0,3, +215,0,102,2,18,0,0,2,11,6,9,3,8,4,2,2,4,231,0,38,255,210,0,249,251,2,0,0,40,0,0,0,0,80,102,69,100,0,64,0,32,255,255,6,20,254,20,1,154,7,109,1,227,96,0,1,223,255,223,0,0,0,0,0,0,0,5,0,0,0,3,0,0,0,44,0,0,0,10,0,0,8,52,0,1,0,0,0,0,20,68,0,3,0,1,0,0,0,44, +0,3,0,10,0,0,8,52,0,4,8,8,0,0,1,254,1,0,0,7,0,254,0,0,0,126,1,195,1,227,1,240,1,246,1,249,2,33,2,65,2,69,2,77,2,185,2,193,2,201,2,211,2,222,2,233,2,238,2,243,3,63,3,67,3,88,3,97,3,119,3,127,3,138,3,140,3,161,3,206,3,225,4,95,4,99,4,115,4,155,4,165,4, +179,4,187,4,196,4,200,4,204,4,249,5,17,5,29,5,86,5,95,5,135,5,138,6,7,6,10,6,12,6,21,6,27,6,31,6,58,6,85,6,90,6,109,6,116,6,123,6,128,6,132,6,135,6,145,6,152,6,164,6,169,6,175,6,190,6,204,6,249,14,63,14,130,14,132,14,136,14,138,14,141,14,151,14,159,14, +163,14,165,14,167,14,171,14,185,14,188,14,205,16,252,29,2,29,9,29,20,29,23,29,31,29,46,29,60,29,91,29,101,29,120,29,123,29,133,29,183,29,191,30,19,30,45,30,77,30,99,30,121,30,153,30,155,30,161,30,173,30,177,30,185,30,189,30,199,30,205,30,221,30,229,30, +235,30,245,30,249,31,21,31,29,31,69,31,77,31,87,31,89,31,91,31,93,31,125,31,180,31,196,31,211,31,219,31,239,31,244,31,254,32,10,32,35,32,38,32,55,32,58,32,63,32,73,32,75,32,95,32,113,32,142,32,156,32,181,32,186,32,189,33,2,33,5,33,15,33,23,33,26,33,29, +33,34,33,36,33,38,33,43,33,46,33,72,33,81,33,95,33,137,34,19,34,21,34,32,34,35,34,45,34,61,34,105,34,139,34,165,34,181,34,184,34,198,34,209,34,233,34,239,35,6,35,21,35,25,35,33,35,40,35,43,35,122,35,125,35,131,35,139,35,149,35,174,35,207,36,35,38,47, +38,139,38,156,38,161,38,177,39,4,39,9,39,39,39,75,39,77,39,82,39,86,39,94,39,117,39,148,39,175,39,190,39,194,39,198,39,220,39,224,39,235,39,247,41,136,41,152,41,235,41,251,42,0,42,47,42,107,43,13,43,26,44,100,44,112,44,119,44,122,44,127,46,24,46,31,46, +37,46,46,167,22,167,31,167,39,167,142,167,145,167,170,167,249,246,197,251,2,251,129,251,149,251,159,251,173,251,233,251,255,254,116,254,252,254,255,255,253,255,255,0,0,0,0,0,32,0,160,1,205,1,230,1,244,1,248,1,252,2,36,2,67,2,76,2,80,2,187,2,198,2,204, +2,214,2,224,2,238,2,243,3,0,3,67,3,88,3,97,3,116,3,122,3,132,3,140,3,142,3,163,3,208,3,240,4,98,4,114,4,144,4,162,4,170,4,186,4,192,4,199,4,203,4,207,5,16,5,26,5,49,5,89,5,97,5,137,6,6,6,9,6,12,6,21,6,27,6,31,6,33,6,64,6,90,6,96,6,116,6,121,6,126,6,131, +6,134,6,145,6,152,6,164,6,169,6,175,6,190,6,204,6,240,14,63,14,129,14,132,14,135,14,138,14,141,14,148,14,153,14,161,14,165,14,167,14,170,14,173,14,187,14,200,16,208,29,2,29,8,29,20,29,22,29,29,29,44,29,48,29,62,29,98,29,119,29,123,29,133,29,155,29,185, +30,0,30,24,30,48,30,84,30,104,30,124,30,155,30,159,30,172,30,176,30,182,30,188,30,198,30,202,30,216,30,224,30,232,30,238,30,248,31,0,31,24,31,32,31,72,31,80,31,89,31,91,31,93,31,95,31,128,31,182,31,198,31,214,31,221,31,242,31,246,32,0,32,16,32,38,32, +47,32,57,32,60,32,69,32,75,32,95,32,112,32,116,32,144,32,160,32,184,32,189,33,2,33,5,33,13,33,21,33,25,33,29,33,34,33,36,33,38,33,42,33,46,33,72,33,80,33,83,33,137,33,144,34,21,34,23,34,35,34,39,34,52,34,65,34,109,34,141,34,178,34,184,34,194,34,205,34, +218,34,239,35,0,35,8,35,24,35,28,35,37,35,43,35,53,35,125,35,128,35,136,35,149,35,155,35,206,36,35,37,0,38,56,38,144,38,160,38,176,39,1,39,6,39,12,39,41,39,77,39,79,39,86,39,88,39,97,39,148,39,152,39,177,39,194,39,197,39,220,39,224,39,230,39,245,41,135, +41,151,41,235,41,250,42,0,42,47,42,106,43,5,43,18,44,100,44,109,44,117,44,121,44,124,46,24,46,31,46,34,46,46,167,8,167,27,167,34,167,137,167,144,167,170,167,248,246,197,251,1,251,82,251,138,251,158,251,170,251,232,251,252,254,112,254,118,254,255,255, +249,255,255,0,0,255,227,255,194,255,185,255,183,255,180,255,179,255,177,255,175,255,174,255,168,255,166,255,165,255,161,255,159,255,157,255,156,255,152,255,148,255,136,255,133,255,113,255,105,255,87,255,85,255,81,255,80,255,79,255,78,255,77,255,63,255, +61,255,47,255,19,255,13,255,9,255,3,254,255,254,253,254,251,254,249,254,227,254,219,254,200,254,198,254,197,254,196,254,73,254,72,254,71,254,63,254,58,254,55,254,54,254,49,254,45,254,40,254,34,254,30,254,28,254,26,254,25,254,16,254,10,253,255,253,251, +253,246,253,232,253,219,253,184,246,115,246,50,246,49,246,47,246,46,246,44,246,38,246,37,246,36,246,35,246,34,246,32,246,31,246,30,246,19,244,17,232,12,232,7,231,253,231,252,231,247,231,235,231,234,231,233,231,227,231,210,231,208,231,199,231,178,231, +177,231,113,231,109,231,107,231,101,231,97,231,95,231,94,231,91,231,81,231,79,231,75,231,73,231,65,231,63,231,53,231,51,231,49,231,47,231,45,231,39,231,37,231,35,231,33,231,31,231,30,231,29,231,28,231,27,231,25,231,24,231,23,231,21,231,20,231,18,231, +17,231,16,231,11,231,9,231,1,231,0,230,255,230,250,230,249,230,230,230,214,230,212,230,211,230,208,230,206,230,204,230,136,230,134,230,127,230,122,230,121,230,119,230,115,230,114,230,113,230,110,230,108,230,83,230,76,230,75,230,34,230,28,230,27,230,26, +230,24,230,21,230,15,230,12,230,9,230,8,229,252,229,250,229,241,229,235,229,227,229,222,229,206,229,205,229,203,229,201,229,198,229,196,229,187,229,185,229,183,229,179,229,170,229,165,229,134,229,51,228,87,228,79,228,75,228,72,228,58,227,235,227,234, +227,232,227,231,227,230,227,229,227,226,227,225,227,223,227,193,227,190,227,189,227,186,227,184,227,163,227,160,227,155,227,146,226,3,225,245,225,163,225,149,225,145,225,99,225,41,224,144,224,140,223,67,223,59,223,55,223,54,223,53,221,157,221,151,221, +149,221,141,100,180,100,176,100,174,100,77,100,76,100,52,99,231,21,28,16,225,16,146,16,138,16,130,16,120,16,62,16,44,13,188,13,187,13,185,12,192,0,1,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,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,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,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,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,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,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,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,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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,16,0,0,0,0,0,0,1,0,0,0,0,32,0,0,0,126,0,0,0,3,0,0,0,160,0,0,1,195, +0,0,0,98,0,0,1,205,0,0,1,227,0,0,1,134,0,0,1,230,0,0,1,240,0,0,1,157,0,0,1,244,0,0,1,246,0,0,1,168,0,0,1,248,0,0,1,249,0,0,1,171,0,0,1,252,0,0,2,33,0,0,1,173,0,0,2,36,0,0,2,65,0,0,1,211,0,0,2,67,0,0,2,69,0,0,1,241,0,0,2,76,0,0,2,77,0,0,1,244,0,0,2,80, +0,0,2,185,0,0,1,246,0,0,2,187,0,0,2,193,0,0,2,96,0,0,2,198,0,0,2,201,0,0,2,103,0,0,2,204,0,0,2,211,0,0,2,107,0,0,2,214,0,0,2,222,0,0,2,115,0,0,2,224,0,0,2,233,0,0,2,124,0,0,2,238,0,0,2,238,0,0,2,134,0,0,2,243,0,0,2,243,0,0,2,135,0,0,3,0,0,0,3,63,0,0, +2,136,0,0,3,67,0,0,3,67,0,0,2,200,0,0,3,88,0,0,3,88,0,0,2,201,0,0,3,97,0,0,3,97,0,0,2,202,0,0,3,116,0,0,3,119,0,0,2,203,0,0,3,122,0,0,3,127,0,0,2,207,0,0,3,132,0,0,3,138,0,0,2,213,0,0,3,140,0,0,3,140,0,0,2,220,0,0,3,142,0,0,3,161,0,0,2,221,0,0,3,163, +0,0,3,206,0,0,2,241,0,0,3,208,0,0,3,225,0,0,3,29,0,0,3,240,0,0,4,95,0,0,3,47,0,0,4,98,0,0,4,99,0,0,3,159,0,0,4,114,0,0,4,115,0,0,3,161,0,0,4,144,0,0,4,155,0,0,3,163,0,0,4,162,0,0,4,165,0,0,3,175,0,0,4,170,0,0,4,179,0,0,3,179,0,0,4,186,0,0,4,187,0,0,3, +189,0,0,4,192,0,0,4,196,0,0,3,191,0,0,4,199,0,0,4,200,0,0,3,196,0,0,4,203,0,0,4,204,0,0,3,198,0,0,4,207,0,0,4,249,0,0,3,200,0,0,5,16,0,0,5,17,0,0,3,243,0,0,5,26,0,0,5,29,0,0,3,245,0,0,5,49,0,0,5,86,0,0,3,249,0,0,5,89,0,0,5,95,0,0,4,31,0,0,5,97,0,0,5, +135,0,0,4,38,0,0,5,137,0,0,5,138,0,0,4,77,0,0,6,6,0,0,6,7,0,0,4,79,0,0,6,9,0,0,6,10,0,0,4,81,0,0,6,12,0,0,6,12,0,0,4,83,0,0,6,21,0,0,6,21,0,0,4,84,0,0,6,27,0,0,6,27,0,0,4,85,0,0,6,31,0,0,6,31,0,0,4,86,0,0,6,33,0,0,6,58,0,0,4,87,0,0,6,64,0,0,6,85,0,0, +4,113,0,0,6,90,0,0,6,90,0,0,4,135,0,0,6,96,0,0,6,109,0,0,4,136,0,0,6,116,0,0,6,116,0,0,4,150,0,0,6,121,0,0,6,123,0,0,4,151,0,0,6,126,0,0,6,128,0,0,4,154,0,0,6,131,0,0,6,132,0,0,4,157,0,0,6,134,0,0,6,135,0,0,4,159,0,0,6,145,0,0,6,145,0,0,4,161,0,0,6,152, +0,0,6,152,0,0,4,162,0,0,6,164,0,0,6,164,0,0,4,163,0,0,6,169,0,0,6,169,0,0,4,164,0,0,6,175,0,0,6,175,0,0,4,165,0,0,6,190,0,0,6,190,0,0,4,166,0,0,6,204,0,0,6,204,0,0,4,167,0,0,6,240,0,0,6,249,0,0,4,168,0,0,14,63,0,0,14,63,0,0,4,178,0,0,14,129,0,0,14,130, +0,0,4,179,0,0,14,132,0,0,14,132,0,0,4,181,0,0,14,135,0,0,14,136,0,0,4,182,0,0,14,138,0,0,14,138,0,0,4,184,0,0,14,141,0,0,14,141,0,0,4,185,0,0,14,148,0,0,14,151,0,0,4,186,0,0,14,153,0,0,14,159,0,0,4,190,0,0,14,161,0,0,14,163,0,0,4,197,0,0,14,165,0,0,14, +165,0,0,4,200,0,0,14,167,0,0,14,167,0,0,4,201,0,0,14,170,0,0,14,171,0,0,4,202,0,0,14,173,0,0,14,185,0,0,4,204,0,0,14,187,0,0,14,188,0,0,4,217,0,0,14,200,0,0,14,205,0,0,4,219,0,0,16,208,0,0,16,252,0,0,4,225,0,0,29,2,0,0,29,2,0,0,5,14,0,0,29,8,0,0,29,9, +0,0,5,15,0,0,29,20,0,0,29,20,0,0,5,17,0,0,29,22,0,0,29,23,0,0,5,18,0,0,29,29,0,0,29,31,0,0,5,20,0,0,29,44,0,0,29,46,0,0,5,23,0,0,29,48,0,0,29,60,0,0,5,26,0,0,29,62,0,0,29,91,0,0,5,39,0,0,29,98,0,0,29,101,0,0,5,69,0,0,29,119,0,0,29,120,0,0,5,73,0,0,29, +123,0,0,29,123,0,0,5,75,0,0,29,133,0,0,29,133,0,0,5,76,0,0,29,155,0,0,29,183,0,0,5,77,0,0,29,185,0,0,29,191,0,0,5,106,0,0,30,0,0,0,30,19,0,0,5,113,0,0,30,24,0,0,30,45,0,0,5,133,0,0,30,48,0,0,30,77,0,0,5,155,0,0,30,84,0,0,30,99,0,0,5,185,0,0,30,104,0, +0,30,121,0,0,5,201,0,0,30,124,0,0,30,153,0,0,5,219,0,0,30,155,0,0,30,155,0,0,5,249,0,0,30,159,0,0,30,161,0,0,5,250,0,0,30,172,0,0,30,173,0,0,5,253,0,0,30,176,0,0,30,177,0,0,5,255,0,0,30,182,0,0,30,185,0,0,6,1,0,0,30,188,0,0,30,189,0,0,6,5,0,0,30,198, +0,0,30,199,0,0,6,7,0,0,30,202,0,0,30,205,0,0,6,9,0,0,30,216,0,0,30,221,0,0,6,13,0,0,30,224,0,0,30,229,0,0,6,19,0,0,30,232,0,0,30,235,0,0,6,25,0,0,30,238,0,0,30,245,0,0,6,29,0,0,30,248,0,0,30,249,0,0,6,37,0,0,31,0,0,0,31,21,0,0,6,39,0,0,31,24,0,0,31,29, +0,0,6,61,0,0,31,32,0,0,31,69,0,0,6,67,0,0,31,72,0,0,31,77,0,0,6,105,0,0,31,80,0,0,31,87,0,0,6,111,0,0,31,89,0,0,31,89,0,0,6,119,0,0,31,91,0,0,31,91,0,0,6,120,0,0,31,93,0,0,31,93,0,0,6,121,0,0,31,95,0,0,31,125,0,0,6,122,0,0,31,128,0,0,31,180,0,0,6,153, +0,0,31,182,0,0,31,196,0,0,6,206,0,0,31,198,0,0,31,211,0,0,6,221,0,0,31,214,0,0,31,219,0,0,6,235,0,0,31,221,0,0,31,239,0,0,6,241,0,0,31,242,0,0,31,244,0,0,7,4,0,0,31,246,0,0,31,254,0,0,7,7,0,0,32,0,0,0,32,10,0,0,7,16,0,0,32,16,0,0,32,35,0,0,7,27,0,0,32, +38,0,0,32,38,0,0,7,47,0,0,32,47,0,0,32,55,0,0,7,48,0,0,32,57,0,0,32,58,0,0,7,57,0,0,32,60,0,0,32,63,0,0,7,59,0,0,32,69,0,0,32,73,0,0,7,63,0,0,32,75,0,0,32,75,0,0,7,68,0,0,32,95,0,0,32,95,0,0,7,69,0,0,32,112,0,0,32,113,0,0,7,70,0,0,32,116,0,0,32,142,0, +0,7,72,0,0,32,144,0,0,32,156,0,0,7,99,0,0,32,160,0,0,32,181,0,0,7,112,0,0,32,184,0,0,32,186,0,0,7,134,0,0,32,189,0,0,32,189,0,0,7,137,0,0,33,2,0,0,33,2,0,0,7,138,0,0,33,5,0,0,33,5,0,0,7,139,0,0,33,13,0,0,33,15,0,0,7,140,0,0,33,21,0,0,33,23,0,0,7,143, +0,0,33,25,0,0,33,26,0,0,7,146,0,0,33,29,0,0,33,29,0,0,7,148,0,0,33,34,0,0,33,34,0,0,7,149,0,0,33,36,0,0,33,36,0,0,7,150,0,0,33,38,0,0,33,38,0,0,7,151,0,0,33,42,0,0,33,43,0,0,7,152,0,0,33,46,0,0,33,46,0,0,7,154,0,0,33,72,0,0,33,72,0,0,7,155,0,0,33,80, +0,0,33,81,0,0,7,156,0,0,33,83,0,0,33,95,0,0,7,158,0,0,33,137,0,0,33,137,0,0,7,171,0,0,33,144,0,0,34,19,0,0,7,172,0,0,34,21,0,0,34,21,0,0,8,48,0,0,34,23,0,0,34,32,0,0,8,49,0,0,34,35,0,0,34,35,0,0,8,59,0,0,34,39,0,0,34,45,0,0,8,60,0,0,34,52,0,0,34,61,0, +0,8,67,0,0,34,65,0,0,34,105,0,0,8,77,0,0,34,109,0,0,34,139,0,0,8,118,0,0,34,141,0,0,34,165,0,0,8,149,0,0,34,178,0,0,34,181,0,0,8,174,0,0,34,184,0,0,34,184,0,0,8,178,0,0,34,194,0,0,34,198,0,0,8,179,0,0,34,205,0,0,34,209,0,0,8,184,0,0,34,218,0,0,34,233, +0,0,8,189,0,0,34,239,0,0,34,239,0,0,8,205,0,0,35,0,0,0,35,6,0,0,8,206,0,0,35,8,0,0,35,21,0,0,8,213,0,0,35,24,0,0,35,25,0,0,8,227,0,0,35,28,0,0,35,33,0,0,8,229,0,0,35,37,0,0,35,40,0,0,8,235,0,0,35,43,0,0,35,43,0,0,8,239,0,0,35,53,0,0,35,122,0,0,8,240, +0,0,35,125,0,0,35,125,0,0,9,54,0,0,35,128,0,0,35,131,0,0,9,55,0,0,35,136,0,0,35,139,0,0,9,59,0,0,35,149,0,0,35,149,0,0,9,63,0,0,35,155,0,0,35,174,0,0,9,64,0,0,35,206,0,0,35,207,0,0,9,84,0,0,36,35,0,0,36,35,0,0,9,86,0,0,37,0,0,0,38,47,0,0,9,87,0,0,38, +56,0,0,38,139,0,0,10,135,0,0,38,144,0,0,38,156,0,0,10,219,0,0,38,160,0,0,38,161,0,0,10,232,0,0,38,176,0,0,38,177,0,0,10,234,0,0,39,1,0,0,39,4,0,0,10,236,0,0,39,6,0,0,39,9,0,0,10,240,0,0,39,12,0,0,39,39,0,0,10,244,0,0,39,41,0,0,39,75,0,0,11,16,0,0,39, +77,0,0,39,77,0,0,11,51,0,0,39,79,0,0,39,82,0,0,11,52,0,0,39,86,0,0,39,86,0,0,11,56,0,0,39,88,0,0,39,94,0,0,11,57,0,0,39,97,0,0,39,117,0,0,11,64,0,0,39,148,0,0,39,148,0,0,11,85,0,0,39,152,0,0,39,175,0,0,11,86,0,0,39,177,0,0,39,190,0,0,11,110,0,0,39,194, +0,0,39,194,0,0,11,124,0,0,39,197,0,0,39,198,0,0,11,125,0,0,39,220,0,0,39,220,0,0,11,127,0,0,39,224,0,0,39,224,0,0,11,128,0,0,39,230,0,0,39,235,0,0,11,129,0,0,39,245,0,0,39,247,0,0,11,135,0,0,41,135,0,0,41,136,0,0,11,138,0,0,41,151,0,0,41,152,0,0,11,140, +0,0,41,235,0,0,41,235,0,0,11,142,0,0,41,250,0,0,41,251,0,0,11,143,0,0,42,0,0,0,42,0,0,0,11,145,0,0,42,47,0,0,42,47,0,0,11,146,0,0,42,106,0,0,42,107,0,0,11,147,0,0,43,5,0,0,43,13,0,0,11,149,0,0,43,18,0,0,43,26,0,0,11,158,0,0,44,100,0,0,44,100,0,0,11,167, +0,0,44,109,0,0,44,112,0,0,11,168,0,0,44,117,0,0,44,119,0,0,11,172,0,0,44,121,0,0,44,122,0,0,11,175,0,0,44,124,0,0,44,127,0,0,11,177,0,0,46,24,0,0,46,24,0,0,11,181,0,0,46,31,0,0,46,31,0,0,11,182,0,0,46,34,0,0,46,37,0,0,11,183,0,0,46,46,0,0,46,46,0,0,11, +187,0,0,167,8,0,0,167,22,0,0,11,188,0,0,167,27,0,0,167,31,0,0,11,203,0,0,167,34,0,0,167,39,0,0,11,208,0,0,167,137,0,0,167,142,0,0,11,214,0,0,167,144,0,0,167,145,0,0,11,220,0,0,167,170,0,0,167,170,0,0,11,222,0,0,167,248,0,0,167,249,0,0,11,223,0,0,246, +197,0,0,246,197,0,0,11,225,0,0,251,1,0,0,251,2,0,0,11,226,0,0,251,82,0,0,251,129,0,0,11,228,0,0,251,138,0,0,251,149,0,0,12,20,0,0,251,158,0,0,251,159,0,0,12,32,0,0,251,170,0,0,251,173,0,0,12,34,0,0,251,232,0,0,251,233,0,0,12,38,0,0,251,252,0,0,251,255, +0,0,12,40,0,0,254,112,0,0,254,116,0,0,12,44,0,0,254,118,0,0,254,252,0,0,12,49,0,0,254,255,0,0,254,255,0,0,12,184,0,0,255,249,0,0,255,253,0,0,12,185,0,1,213,90,0,1,213,90,0,0,12,190,0,1,214,112,0,1,214,163,0,0,12,191,0,1,215,246,0,1,215,255,0,0,12,243, +0,6,2,10,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,0,0,0,0,0,0,2,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,1,0,0,0,0,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,12,0,13,0,14,0,15,0,16,0,17,0,18,0,19,0,20,0,21,0,22,0,23,0,24, +0,25,0,26,0,27,0,28,0,29,0,30,0,31,0,32,0,33,0,34,0,35,0,36,0,37,0,38,0,39,0,40,0,41,0,42,0,43,0,44,0,45,0,46,0,47,0,48,0,49,0,50,0,51,0,52,0,53,0,54,0,55,0,56,0,57,0,58,0,59,0,60,0,61,0,62,0,63,0,64,0,65,0,66,0,67,0,68,0,69,0,70,0,71,0,72,0,73,0,74, +0,75,0,76,0,77,0,78,0,79,0,80,0,81,0,82,0,83,0,84,0,85,0,86,0,87,0,88,0,89,0,90,0,91,0,92,0,93,0,94,0,95,0,96,0,97,0,0,0,134,0,135,0,137,0,139,0,147,0,152,0,158,0,163,0,162,0,164,0,166,0,165,0,167,0,169,0,171,0,170,0,172,0,173,0,175,0,174,0,176,0,177, +0,179,0,181,0,180,0,182,0,184,0,183,0,188,0,187,0,189,0,190,7,43,0,114,0,100,0,101,0,105,7,45,0,120,0,161,0,112,0,107,7,149,0,118,0,106,8,108,0,136,0,154,8,56,0,115,8,112,8,113,0,103,0,119,8,30,8,45,8,43,3,14,8,64,0,108,0,124,2,247,0,168,0,186,0,129, +0,99,0,110,8,52,1,84,8,84,8,34,0,109,0,125,7,47,0,98,0,130,0,133,0,151,1,20,1,21,7,30,7,31,7,39,7,40,7,35,7,36,0,185,10,33,0,193,1,58,0,0,7,124,7,57,7,58,11,226,11,227,7,44,0,121,7,37,7,41,7,49,0,132,0,140,0,131,0,141,0,138,0,143,0,144,0,145,0,142,0, +149,0,150,0,0,0,148,0,156,0,157,0,155,0,243,2,103,2,121,0,113,2,117,2,118,2,119,0,122,2,122,2,120,2,104,0,0,0,184,0,203,0,184,0,203,0,170,1,145,0,184,0,102,0,0,0,184,0,135,2,127,0,2,0,2,0,2,0,2,0,2,0,184,0,195,0,203,0,2,0,203,0,184,0,184,1,203,1,137, +1,186,0,203,0,166,0,252,0,203,0,131,0,242,1,10,3,199,1,55,0,131,0,190,0,0,0,88,4,33,0,203,0,143,0,156,0,2,0,2,0,143,3,231,0,117,3,188,0,211,0,201,0,219,0,117,3,231,1,57,3,186,0,203,1,211,0,33,1,223,0,184,0,137,0,2,0,2,0,2,0,2,0,2,3,190,0,137,0,195,3, +190,0,123,3,190,3,88,1,31,1,109,0,164,1,174,0,0,0,123,0,184,1,111,0,127,2,123,0,184,2,82,0,143,0,205,4,209,0,0,0,205,0,135,0,135,0,147,0,164,0,111,0,205,0,203,0,184,0,131,1,145,0,221,0,180,0,139,0,244,0,152,2,233,0,90,0,180,0,186,0,197,4,33,0,254,0,14, +0,2,0,2,0,2,1,213,0,246,0,127,2,170,2,61,2,102,0,139,0,197,0,143,0,154,0,154,1,131,0,213,0,115,4,0,1,10,0,254,0,225,5,213,2,43,0,164,0,180,0,156,0,0,0,98,0,156,5,213,5,152,0,135,2,127,5,213,5,213,5,240,0,164,0,0,0,29,6,184,6,20,7,35,1,211,0,184,0,203, +0,166,1,188,1,49,2,78,0,211,1,10,0,123,0,84,3,92,3,113,3,219,1,133,4,35,4,119,3,233,0,143,2,0,3,96,0,106,0,207,5,213,6,20,0,143,7,35,0,143,6,102,1,121,4,96,4,96,4,96,4,123,0,0,0,123,2,119,4,96,1,170,0,233,6,20,7,98,3,248,0,123,2,33,0,197,0,156,0,127, +2,123,0,0,0,180,2,82,5,78,5,78,4,209,0,102,0,156,0,156,0,102,0,156,0,143,0,102,0,156,0,143,6,16,0,205,3,250,0,131,0,145,2,254,1,72,4,70,3,63,0,143,0,123,4,76,0,152,0,162,0,0,0,39,0,111,0,0,0,111,3,53,0,106,0,111,0,123,5,141,5,141,5,141,5,141,0,170,0, +170,0,45,5,141,3,150,2,123,0,246,0,127,2,170,1,51,2,61,0,156,2,102,1,139,0,143,2,246,0,205,0,111,3,68,0,55,0,102,0,29,5,238,0,133,1,180,6,20,0,0,7,125,0,115,5,213,0,0,20,0,183,7,6,5,4,3,2,1,0,44,32,16,176,2,37,73,100,176,64,81,88,32,200,89,33,45,44,176, +2,37,73,100,176,64,81,88,32,200,89,33,45,44,32,16,7,32,176,0,80,176,13,121,32,184,255,255,80,88,4,27,5,89,176,5,28,176,3,37,8,176,4,37,35,225,32,176,0,80,176,13,121,32,184,255,255,80,88,4,27,5,89,176,5,28,176,3,37,8,225,45,44,75,80,88,32,184,1,23,69, +68,89,33,45,44,176,2,37,69,96,68,45,44,75,83,88,176,2,37,176,2,37,69,68,89,33,33,45,44,69,68,45,44,176,2,37,176,2,37,73,176,5,37,176,5,37,73,96,176,32,99,104,32,138,16,138,35,58,138,16,101,58,45,0,0,0,2,0,8,0,2,255,255,0,3,0,2,0,104,254,150,4,104,5,164, +0,3,0,7,0,31,188,0,4,1,20,0,0,0,6,1,20,182,1,8,5,131,2,4,0,47,196,212,236,49,0,16,212,236,212,236,48,19,17,33,17,37,33,17,33,104,4,0,252,115,3,27,252,229,254,150,7,14,248,242,114,6,41,0,0,0,0,2,2,4,0,0,2,207,5,213,0,5,0,9,0,31,64,15,3,135,6,134,0,136, +8,4,3,7,1,3,6,0,10,16,212,60,236,50,57,57,49,0,47,228,252,236,48,1,51,17,3,35,3,17,51,21,35,2,4,203,21,161,21,203,203,5,213,253,113,254,155,1,101,253,184,254,0,2,1,82,3,170,3,127,5,213,0,3,0,7,0,29,64,14,5,1,137,4,0,136,8,0,4,2,6,4,4,8,16,212,236,220, +236,49,0,16,244,60,236,50,48,1,17,35,17,35,17,35,17,3,127,174,209,174,5,213,253,213,2,43,253,213,2,43,0,2,0,2,0,0,4,205,5,190,0,27,0,31,0,74,64,48,28,23,7,140,3,0,25,5,1,30,21,9,140,19,15,11,17,13,31,30,29,28,27,26,24,23,22,19,18,17,16,15,14,13,12,10, +9,8,5,4,3,2,1,0,26,6,20,32,16,212,204,23,57,49,0,47,60,212,60,60,252,60,60,212,60,60,196,50,236,50,50,48,1,3,51,19,51,3,51,21,33,3,51,21,33,3,35,19,35,3,35,19,33,53,33,19,33,53,33,19,1,35,3,51,2,172,104,245,105,160,105,244,254,231,84,250,254,223,104, +160,105,246,105,159,104,254,254,1,41,84,254,246,1,47,104,1,8,245,84,246,5,190,254,97,1,159,254,97,154,254,178,153,254,98,1,158,254,98,1,158,153,1,78,154,1,159,253,199,254,178,0,3,0,190,254,211,4,90,6,20,0,6,0,13,0,47,0,100,64,57,8,40,36,0,7,41,24,4,37, +20,47,16,23,19,1,37,139,36,142,31,40,143,30,20,139,19,142,1,143,14,33,30,16,4,6,36,8,44,5,0,11,6,27,19,5,40,32,14,3,0,7,30,23,15,3,7,48,16,212,23,60,236,23,50,252,60,236,16,252,228,238,49,0,47,198,50,196,238,246,238,16,238,198,246,238,17,18,57,17,57, +17,18,23,57,17,18,57,48,1,17,62,1,53,52,38,39,17,14,1,21,20,22,19,35,3,46,1,39,53,30,1,23,17,46,1,53,52,54,55,53,51,23,30,1,23,21,46,1,39,17,30,1,21,20,6,7,2,180,110,124,112,222,104,117,109,212,100,1,102,201,98,100,203,99,200,202,211,191,100,1,79,162, +84,85,161,80,206,216,233,188,2,68,254,78,3,116,100,93,103,209,1,157,4,112,94,86,100,251,192,1,45,5,46,41,180,62,66,2,1,202,31,182,150,157,187,14,235,235,5,30,26,173,43,47,4,254,81,31,194,154,154,206,9,0,0,0,0,5,0,33,0,0,4,176,5,152,0,11,0,26,0,30,0,42, +0,57,0,86,64,47,30,55,29,40,34,28,15,27,3,9,146,15,34,146,55,147,40,146,46,145,15,147,3,146,24,28,27,43,31,30,29,6,10,21,11,0,10,12,37,10,52,11,31,10,43,12,58,16,196,212,236,252,236,16,238,254,238,57,57,17,18,57,57,49,0,47,238,238,246,238,254,238,16, +238,17,57,17,57,17,18,57,18,57,48,1,20,22,51,50,54,53,52,38,35,34,6,7,52,54,51,50,22,23,30,1,21,20,6,35,34,38,1,39,1,23,37,20,22,51,50,54,53,52,38,35,34,6,7,52,54,51,50,22,23,30,1,21,20,6,35,34,38,2,184,105,78,77,107,108,76,78,105,135,184,134,64,115, +46,46,50,186,135,136,182,254,72,35,4,18,41,252,23,105,79,77,108,108,77,77,107,135,184,135,64,117,45,45,49,186,134,135,184,1,63,78,106,107,77,77,108,106,79,135,185,48,46,47,116,63,133,186,183,1,26,96,1,162,96,229,79,105,107,77,77,107,106,78,135,185,48, +45,45,117,65,134,185,184,0,0,0,0,2,0,57,255,227,4,197,5,240,0,42,0,55,0,179,64,98,17,16,2,18,15,23,12,13,12,14,23,13,13,12,45,44,2,46,43,23,0,1,0,50,51,52,53,54,5,49,55,23,1,1,0,66,55,12,9,6,1,5,7,15,49,13,24,0,43,3,34,7,49,151,18,34,33,37,151,30,150, +18,153,7,13,0,40,1,7,6,3,33,12,8,4,55,43,33,24,40,27,15,33,4,19,8,40,18,33,27,8,13,16,27,46,18,21,56,16,220,236,196,252,196,16,198,238,16,238,17,57,17,18,57,17,57,57,17,18,57,18,23,57,17,57,49,0,47,198,228,246,238,214,206,16,238,17,18,23,57,17,18,57, +17,23,57,48,75,83,88,7,16,14,237,17,23,57,7,16,14,237,17,23,57,7,16,5,237,7,16,5,237,17,23,57,89,34,9,1,62,1,53,52,47,1,51,21,20,6,7,23,35,39,14,1,35,34,0,53,52,54,55,46,1,53,52,54,51,50,22,23,21,46,1,35,34,6,21,20,22,7,14,1,21,20,22,51,50,54,55,62,1, +55,2,35,1,160,39,38,3,1,164,74,75,170,213,78,83,186,106,216,254,230,138,139,50,48,199,173,65,131,70,59,125,69,97,112,58,54,92,91,200,155,42,92,44,27,35,16,3,139,253,209,49,150,104,32,70,7,39,161,243,88,229,109,70,68,1,13,204,137,234,100,72,138,71,150, +174,24,23,183,39,37,91,77,59,129,207,73,163,92,151,199,24,23,15,23,13,0,0,0,1,2,16,3,170,2,190,5,213,0,3,0,18,183,1,0,136,4,0,4,2,4,16,212,236,49,0,16,244,196,48,1,17,35,17,2,190,174,5,213,253,213,2,43,0,0,0,0,1,1,170,254,242,3,117,6,18,0,13,0,31,64, +15,6,156,0,155,14,13,7,0,3,18,6,0,24,10,14,16,212,236,50,236,17,57,57,49,0,16,252,236,48,1,6,2,21,20,18,23,35,38,2,53,52,18,55,3,117,133,131,131,133,160,151,148,148,151,6,18,228,254,59,230,229,254,58,230,238,1,195,224,223,1,196,236,0,1,1,92,254,242,3, +39,6,18,0,13,0,31,64,15,7,156,0,155,14,7,1,11,8,0,24,4,18,11,14,16,212,252,236,50,17,57,57,49,0,16,252,236,48,1,51,22,18,21,20,2,7,35,54,18,53,52,2,1,92,160,151,148,148,151,160,133,131,131,6,18,236,254,60,223,225,254,60,236,232,1,198,227,228,1,198,0, +0,1,0,166,2,74,4,43,5,240,0,17,0,78,64,44,16,13,11,0,4,12,9,7,4,2,4,8,3,157,5,17,12,157,10,1,14,150,18,8,12,10,3,9,6,17,3,1,3,2,0,25,15,4,11,9,25,13,6,18,16,212,60,236,50,220,60,236,50,23,57,17,18,23,57,49,0,16,244,212,60,236,50,196,236,50,23,57,18,23, +57,48,1,13,1,7,37,17,35,17,5,39,45,1,55,5,17,51,17,37,4,43,254,154,1,102,57,254,176,115,254,176,57,1,102,254,154,57,1,80,115,1,80,4,223,194,195,98,203,254,135,1,121,203,98,195,194,99,203,1,121,254,135,203,0,0,0,1,0,88,0,113,4,121,4,147,0,11,0,39,64,20, +0,161,9,1,160,5,161,7,3,12,2,26,4,0,28,8,26,10,6,12,16,212,60,236,252,60,236,49,0,16,212,60,236,252,60,236,48,1,17,33,21,33,17,35,17,33,53,33,17,2,188,1,189,254,67,168,254,68,1,188,4,147,254,68,170,254,68,1,188,170,1,188,0,1,1,147,254,225,2,242,1,47, +0,5,0,24,64,11,3,163,0,162,6,3,4,1,29,0,6,16,212,236,212,204,49,0,16,252,236,48,1,51,21,3,35,19,1,246,252,197,154,99,1,47,207,254,129,1,127,0,0,0,0,1,1,100,1,223,3,109,2,131,0,3,0,17,182,0,160,2,4,1,0,4,16,212,196,49,0,16,212,236,48,1,33,21,33,1,100, +2,9,253,247,2,131,164,0,1,1,233,0,0,2,229,1,49,0,3,0,16,182,0,162,2,1,29,0,4,16,212,236,49,0,47,236,48,1,51,17,35,1,233,252,252,1,49,254,207,0,0,0,1,0,102,255,66,4,55,5,213,0,3,0,24,64,11,2,0,136,4,1,30,0,2,30,3,4,16,212,236,212,236,49,0,16,244,196,48, +1,51,1,35,3,121,190,252,238,191,5,213,249,109,0,3,0,133,255,227,4,76,5,240,0,11,0,23,0,35,1,10,64,26,3,165,9,18,151,30,12,151,24,150,30,153,36,21,30,27,6,33,0,27,34,15,30,33,31,36,16,252,236,236,212,236,16,238,49,0,16,228,244,236,16,238,212,238,48,64, +214,47,0,47,1,47,2,47,3,47,4,47,5,47,6,47,7,47,8,47,9,47,10,47,11,63,0,63,1,63,2,63,3,63,4,63,5,63,6,63,7,63,8,63,9,63,10,63,11,79,0,79,1,79,2,79,10,79,11,95,0,95,1,95,2,95,10,95,11,159,0,159,1,159,2,159,3,159,4,159,5,159,6,159,7,159,8,159,9,159,10,159, +11,175,0,175,1,175,2,175,3,175,4,175,5,175,6,175,7,175,8,175,9,175,10,175,11,191,0,191,1,191,2,191,3,191,4,191,5,191,6,191,7,191,8,191,9,191,10,191,11,70,47,0,47,1,47,2,47,3,47,4,47,5,47,6,47,7,47,8,47,9,47,10,47,11,95,0,95,1,95,2,95,3,95,4,95,5,95,6, +95,7,95,8,95,9,95,10,95,11,191,0,191,1,191,2,191,3,191,4,191,5,191,6,191,7,191,8,191,9,191,10,191,11,36,93,1,93,1,52,54,51,50,22,21,20,6,35,34,38,19,34,2,17,16,18,51,50,18,17,16,2,39,50,18,17,16,2,35,34,2,17,16,18,1,227,77,54,56,80,79,57,56,75,133,141, +139,139,141,142,139,139,142,239,245,245,239,239,244,244,2,238,55,80,80,55,56,78,76,2,156,254,208,254,201,254,202,254,208,1,48,1,54,1,55,1,48,160,254,120,254,129,254,130,254,120,1,136,1,126,1,127,1,136,0,0,0,1,0,246,0,0,4,70,5,213,0,10,0,38,64,20,3,151, +4,2,151,5,136,7,0,151,9,8,35,6,30,3,0,35,1,11,16,212,236,196,252,236,49,0,47,236,50,244,236,212,236,48,37,33,17,5,53,37,51,17,33,21,33,1,14,1,58,254,174,1,80,202,1,54,252,200,170,4,117,76,184,74,250,213,170,0,0,0,0,1,0,152,0,0,4,35,5,240,0,28,0,81,64, +41,0,28,37,5,6,5,24,25,26,3,23,27,37,6,6,5,66,16,17,167,13,151,20,150,4,0,151,2,0,16,10,2,1,10,30,23,34,16,3,36,29,16,252,196,252,236,192,192,17,18,57,49,0,47,236,50,244,236,244,204,48,75,83,88,7,16,5,237,17,23,57,7,16,5,237,23,50,89,34,37,33,21,33,53, +54,0,55,62,1,53,52,38,35,34,6,7,53,62,1,51,50,4,21,20,6,7,14,1,1,117,2,174,252,117,187,1,24,53,100,70,147,128,91,200,112,103,199,97,219,1,11,89,100,56,213,170,170,170,197,1,46,62,122,151,79,125,142,66,67,204,49,50,233,189,96,192,116,65,230,0,0,1,0,137, +255,227,4,55,5,240,0,40,0,71,64,41,0,19,151,21,10,139,9,166,13,151,6,31,139,32,166,28,151,35,150,6,153,21,169,41,22,19,0,3,20,25,30,38,16,30,3,34,31,20,9,31,41,16,252,196,196,252,236,212,236,17,23,57,49,0,16,236,228,244,236,244,236,16,238,246,238,16, +238,57,48,1,30,1,21,20,4,35,34,38,39,53,30,1,51,50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53,62,1,51,50,4,21,20,6,3,8,147,156,254,235,245,103,214,103,102,198,98,166,178,178,152,154,154,139,156,145,134,89,190,104,121,189,73,218,1,5,137,3,31,39, +199,149,206,235,38,36,201,53,52,150,141,130,153,166,122,109,115,123,40,40,186,32,32,219,181,123,164,0,0,0,0,2,0,102,0,0,4,111,5,213,0,2,0,13,0,66,64,31,1,13,3,13,0,3,3,13,66,0,3,11,7,151,5,1,3,136,9,1,12,10,0,30,8,4,6,15,12,36,14,16,252,252,212,60,236, +50,17,57,49,0,47,228,212,60,236,50,18,57,48,75,83,88,7,16,4,201,7,16,5,201,89,34,9,1,33,3,51,17,51,21,35,17,35,17,33,53,2,223,254,41,1,215,33,234,199,199,201,253,135,5,29,252,235,3,205,252,51,164,254,156,1,100,191,0,0,1,0,143,255,227,4,45,5,213,0,29, +0,61,64,34,4,7,29,26,151,7,17,139,16,142,20,151,13,2,151,0,136,13,153,7,170,30,3,30,0,23,30,1,10,34,0,16,31,30,16,252,196,252,196,236,16,238,49,0,16,228,228,244,236,16,238,246,238,16,254,196,18,57,48,19,33,21,33,17,62,1,51,50,0,21,20,0,35,34,38,39,53, +30,1,51,50,54,53,52,38,35,34,6,7,207,2,244,253,196,43,87,44,232,1,16,254,227,247,119,197,78,92,186,97,167,181,187,167,81,154,70,5,213,170,254,145,16,15,254,238,234,236,254,240,32,32,205,50,49,176,162,160,178,37,37,0,2,0,133,255,227,4,76,5,240,0,24,0, +36,0,61,64,35,7,31,25,151,10,31,151,16,10,171,4,1,139,0,142,4,151,22,150,16,153,37,34,30,0,38,13,34,7,6,28,1,19,31,37,16,252,236,236,252,228,236,49,0,16,228,244,236,244,236,16,229,16,238,16,238,17,57,48,1,21,46,1,35,34,2,17,62,1,51,50,18,21,20,2,35,32, +2,17,16,0,33,50,22,1,34,6,21,20,22,51,50,54,53,52,38,3,223,63,142,77,192,198,48,170,110,216,237,244,221,254,252,242,1,35,1,20,74,148,254,221,129,148,148,129,134,136,136,5,180,186,37,39,254,223,254,231,100,107,254,247,243,242,254,246,1,117,1,145,1,122, +1,141,31,253,108,186,164,164,186,177,173,174,176,0,0,0,1,0,139,0,0,4,55,5,213,0,6,0,53,64,25,5,37,2,3,2,3,37,4,5,4,66,5,151,0,136,3,5,3,1,4,1,34,0,31,7,16,252,236,196,17,57,57,49,0,47,244,236,48,75,83,88,7,16,5,237,7,16,5,237,89,34,19,33,21,1,35,1,33, +139,3,172,253,234,211,2,8,253,53,5,213,86,250,129,5,43,0,0,3,0,131,255,227,4,78,5,240,0,11,0,35,0,47,0,67,64,37,24,12,0,151,39,6,151,30,45,151,18,150,30,153,39,169,48,24,12,36,42,30,21,36,30,15,9,30,21,27,34,3,30,15,33,31,48,16,252,196,236,252,196,236, +16,238,16,238,17,57,57,49,0,16,236,228,244,236,16,238,16,238,57,57,48,1,34,6,21,20,22,51,50,54,53,52,38,37,46,1,53,52,54,51,50,22,21,20,6,7,30,1,21,20,4,35,34,36,53,52,54,19,20,22,51,50,54,53,52,38,35,34,6,2,104,135,147,149,133,136,147,149,254,202,129, +145,242,208,209,242,145,129,150,159,254,254,228,228,254,255,159,77,128,121,122,128,127,123,121,128,2,197,151,138,138,153,151,140,137,152,84,33,180,127,178,209,209,178,127,180,33,33,200,159,202,228,227,201,160,201,1,98,120,126,126,120,122,128,129,0,0, +0,0,2,0,127,255,227,4,70,5,240,0,11,0,36,0,59,64,34,19,6,0,151,22,171,16,13,139,12,142,16,151,34,6,151,28,150,34,153,37,19,6,3,1,31,34,9,30,12,38,25,31,37,16,252,228,236,252,236,236,49,0,16,228,244,236,16,238,246,238,16,245,238,17,57,48,1,50,54,53,52, +38,35,34,6,21,20,22,3,53,30,1,51,50,18,17,14,1,35,34,2,53,52,18,51,32,18,17,16,0,33,34,38,2,84,129,147,147,129,134,136,135,225,63,142,77,192,197,47,170,110,216,237,243,222,1,4,242,254,221,254,235,73,148,2,150,186,164,164,186,177,173,174,176,253,137,186, +37,39,1,33,1,25,100,107,1,10,244,241,1,9,254,138,254,111,254,135,254,115,31,0,0,2,1,233,0,0,2,229,4,39,0,3,0,7,0,27,64,13,2,162,0,172,4,162,6,5,1,29,4,0,8,16,212,60,236,50,49,0,47,236,244,236,48,1,51,17,35,17,51,17,35,1,233,252,252,252,252,4,39,254,209, +254,57,254,207,0,0,0,0,2,1,147,254,225,2,242,4,39,0,5,0,9,0,37,64,19,8,162,6,3,163,0,162,6,172,10,3,4,0,29,1,7,29,6,10,16,212,252,212,252,212,204,49,0,16,228,252,236,16,238,48,1,51,21,3,35,19,3,51,17,35,1,246,252,197,154,99,13,252,252,1,47,207,254,129, +1,127,3,199,254,209,0,0,1,0,88,0,141,4,121,4,119,0,6,0,33,64,18,5,4,2,1,0,5,3,174,6,173,7,1,2,0,40,4,39,7,16,252,236,50,57,49,0,16,244,236,23,57,48,9,2,21,1,53,1,4,121,252,174,3,82,251,223,4,33,3,193,254,192,254,195,183,1,162,166,1,162,0,0,2,0,88,1,96, +4,121,3,162,0,3,0,7,0,27,64,12,4,160,6,2,160,0,8,5,1,4,0,8,16,212,60,196,50,49,0,16,212,236,212,236,48,19,33,21,33,17,33,21,33,88,4,33,251,223,4,33,251,223,2,12,172,2,66,170,0,0,0,1,0,88,0,141,4,121,4,119,0,6,0,33,64,18,6,5,3,2,0,5,4,174,1,173,7,6,2, +40,4,0,39,7,16,252,60,236,57,49,0,16,244,236,23,57,48,19,53,1,21,1,53,1,88,4,33,251,223,3,82,3,193,182,254,94,166,254,94,183,1,61,0,2,0,244,0,0,4,16,5,240,0,30,0,34,0,123,64,66,11,10,9,8,7,5,12,6,37,25,26,25,3,4,2,2,5,37,26,26,25,66,29,26,5,2,4,6,25, +15,0,31,16,139,15,141,12,151,19,150,31,134,33,6,32,25,22,9,5,1,0,26,32,9,0,3,1,9,41,22,15,1,32,3,31,35,16,212,236,196,212,212,236,16,238,17,18,57,17,18,57,17,18,57,18,57,49,0,47,238,246,254,244,238,16,205,17,57,57,23,57,48,75,83,88,7,16,4,237,17,23,57, +7,16,4,237,17,23,57,89,34,1,35,53,52,54,63,1,62,1,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,15,1,14,1,29,1,3,51,21,35,2,172,190,61,84,90,62,47,131,109,78,178,98,94,191,104,186,221,67,94,88,69,38,197,203,203,1,145,154,98,137,82,89,59,88,49,89,110,69, +68,188,57,56,192,161,76,131,92,86,66,84,61,47,254,242,254,0,0,0,2,0,27,254,193,4,154,5,115,0,11,0,52,0,112,64,49,40,43,36,26,23,3,14,12,9,27,52,3,175,23,9,175,12,17,39,36,175,43,23,30,175,49,43,53,39,13,6,40,12,0,6,43,20,0,26,13,46,12,20,33,43,12,45, +46,53,16,220,236,252,196,16,254,60,196,16,238,17,18,57,17,18,57,49,0,16,196,212,252,196,16,254,196,213,196,238,16,238,57,57,17,18,57,17,18,57,17,18,57,48,64,13,128,5,128,6,128,7,128,19,128,20,128,21,6,1,93,1,52,38,35,34,6,21,20,22,51,50,54,19,35,53,14, +1,35,34,38,53,52,54,51,50,22,23,53,52,38,35,34,0,17,16,0,33,50,54,55,23,14,1,35,32,0,17,16,0,33,50,18,21,4,14,128,107,107,129,129,107,107,128,140,144,37,131,82,161,211,211,161,80,134,36,176,145,246,254,221,1,74,1,18,54,108,57,48,63,123,58,254,155,254, +93,1,120,1,60,209,250,2,33,129,155,155,129,130,155,155,254,232,111,63,68,242,188,188,242,70,61,63,156,190,254,129,254,185,254,183,254,122,20,21,135,25,24,1,210,1,140,1,134,1,206,254,246,224,0,2,0,37,0,0,4,172,5,213,0,2,0,10,0,152,64,65,0,37,1,0,4,5,4, +2,37,5,4,7,37,5,4,6,37,5,5,4,9,37,3,10,8,37,3,10,1,37,10,3,10,0,37,2,0,3,3,10,66,0,3,7,151,1,176,3,136,9,5,9,8,7,6,4,3,2,1,0,9,5,47,10,11,16,220,236,23,57,49,0,47,60,228,252,236,18,57,48,75,83,88,7,16,8,237,7,16,5,237,7,5,237,7,5,237,7,16,5,237,7,5,237, +7,5,237,7,16,8,237,89,34,178,7,3,1,1,93,64,26,10,0,15,0,143,0,143,0,4,3,1,11,2,4,3,12,4,9,7,6,8,134,1,137,2,8,93,0,93,1,3,33,1,51,1,35,3,33,3,35,2,104,213,1,170,254,177,245,1,201,209,110,253,245,108,209,5,35,253,4,3,174,250,43,1,133,254,123,0,0,3,0,166, +0,0,4,113,5,213,0,8,0,17,0,32,0,61,64,35,25,0,151,10,9,151,18,136,1,151,10,177,31,17,11,25,31,19,8,2,5,0,14,30,22,5,50,28,49,9,0,30,18,48,33,16,252,236,50,252,236,212,236,17,23,57,57,57,49,0,47,236,236,244,236,16,238,57,48,1,17,51,50,54,53,52,38,35,3, +17,51,50,54,53,52,38,35,37,33,50,22,21,20,6,7,30,1,21,20,4,41,1,1,113,239,176,150,158,168,239,235,146,131,129,148,254,74,1,186,229,248,131,131,147,167,254,246,254,249,254,70,2,201,253,221,123,141,146,137,2,102,254,62,112,125,113,100,166,198,181,137,158, +20,22,207,160,203,207,0,1,0,139,255,227,4,49,5,240,0,25,0,46,64,26,25,179,0,178,22,151,3,13,179,12,178,16,151,9,150,3,153,26,19,50,12,0,49,6,48,26,16,252,236,50,236,49,0,16,228,244,236,244,236,16,238,246,238,48,37,14,1,35,32,0,17,16,0,33,50,22,23,21, +46,1,35,34,2,17,16,18,51,50,54,55,4,49,77,162,91,254,225,254,195,1,63,1,29,91,162,77,74,170,86,197,196,196,197,88,169,73,53,41,41,1,150,1,112,1,110,1,153,41,41,207,61,64,254,208,254,205,254,206,254,208,64,61,0,0,0,2,0,137,0,0,4,82,5,213,0,8,0,17,0,40, +64,21,6,151,9,136,0,151,15,6,0,15,9,7,3,50,12,49,7,30,16,48,18,16,252,236,252,236,17,57,57,57,57,49,0,47,236,244,236,48,37,32,54,17,16,38,33,35,17,19,32,0,17,16,0,41,1,17,1,180,0,255,202,201,255,0,96,100,1,86,1,68,254,188,254,170,254,209,166,251,1,72, +1,75,251,251,119,5,47,254,148,254,128,254,130,254,149,5,213,0,0,1,0,197,0,0,4,78,5,213,0,11,0,41,64,22,6,151,4,2,151,0,136,8,151,4,177,10,1,5,9,49,7,3,30,0,51,12,16,252,236,50,252,196,196,49,0,47,236,236,244,236,16,238,48,19,33,21,33,17,33,21,33,17,33, +21,33,197,3,118,253,84,2,142,253,114,2,191,252,119,5,213,170,254,70,170,253,227,170,0,0,0,0,1,0,233,0,0,4,88,5,213,0,9,0,36,64,19,6,151,4,2,151,0,136,4,177,8,5,1,49,7,3,30,0,52,10,16,252,236,50,252,196,49,0,47,236,244,236,16,238,48,19,33,21,33,17,33, +21,33,17,35,233,3,111,253,92,2,101,253,155,203,5,213,170,254,72,170,253,55,0,0,0,1,0,102,255,227,4,80,5,240,0,29,0,60,64,33,25,26,0,22,3,26,151,28,22,151,3,13,179,12,178,16,151,9,150,3,153,30,27,25,30,12,0,54,19,50,6,53,30,16,252,236,252,196,252,196, +49,0,16,228,244,236,244,236,16,254,212,238,17,18,57,17,57,48,37,14,1,35,32,0,17,16,0,33,50,22,23,21,46,1,35,34,2,17,16,18,51,50,54,55,17,35,53,33,4,80,81,203,118,254,228,254,196,1,64,1,29,94,172,80,81,170,95,197,197,191,198,67,101,41,217,1,154,123,75, +77,1,151,1,111,1,110,1,153,53,54,207,77,73,254,207,254,206,254,201,254,213,31,33,1,145,166,0,0,0,1,0,137,0,0,4,72,5,213,0,11,0,38,64,20,8,151,2,177,4,0,136,10,6,7,3,30,5,49,9,1,30,0,48,12,16,252,236,50,252,236,50,49,0,47,60,228,50,252,236,48,19,51,17, +33,17,51,17,35,17,33,17,35,137,203,2,41,203,203,253,215,203,5,213,253,156,2,100,250,43,2,199,253,57,0,0,0,0,1,0,201,0,0,4,6,5,213,0,11,0,37,64,19,10,2,151,0,136,8,4,151,6,5,1,55,3,30,7,0,55,9,12,16,212,236,50,252,236,50,49,0,47,236,50,244,236,50,48,19, +33,21,33,17,33,21,33,53,33,17,33,201,3,61,254,199,1,57,252,195,1,57,254,199,5,213,170,251,127,170,170,4,129,0,0,0,0,1,0,109,255,227,3,188,5,213,0,17,0,44,64,23,12,7,8,1,0,178,4,151,15,8,151,10,136,15,153,18,9,7,30,11,0,53,18,16,252,212,252,196,49,0,16, +228,244,236,16,238,246,206,17,57,57,48,55,53,30,1,51,50,54,53,17,33,53,33,17,16,6,35,34,38,109,91,194,104,143,113,254,131,2,71,211,247,96,190,61,236,81,81,149,203,3,68,170,252,18,254,230,234,44,0,0,0,0,1,0,137,0,0,4,201,5,213,0,11,0,151,64,33,8,37,9, +8,5,6,5,7,37,6,5,66,8,5,2,3,3,0,180,10,6,8,5,4,3,6,1,9,1,30,0,48,12,16,252,236,50,16,192,23,57,49,0,47,60,236,50,23,57,48,75,83,88,7,5,237,7,16,8,237,89,34,178,8,4,1,1,93,64,76,7,5,22,5,23,8,38,5,38,8,54,2,70,2,85,2,87,8,88,9,100,2,122,5,121,8,123,9, +14,2,3,1,4,7,5,0,6,2,7,22,5,23,8,39,5,44,6,43,7,38,8,58,3,73,3,71,6,71,7,91,3,87,5,88,6,88,7,87,8,107,3,122,3,120,7,23,93,0,93,19,51,17,1,51,9,1,35,1,7,17,35,137,203,2,119,237,253,187,2,86,244,254,25,154,203,5,213,253,104,2,152,253,158,252,141,2,236, +164,253,184,0,0,0,1,0,215,0,0,4,115,5,213,0,5,0,24,64,12,2,151,0,136,4,1,30,3,49,0,52,6,16,252,236,236,49,0,47,228,236,48,19,51,17,33,21,33,215,203,2,209,252,100,5,213,250,213,170,0,0,1,0,86,0,0,4,121,5,213,0,12,0,133,64,44,8,2,3,2,7,3,3,2,10,1,2,1,9, +2,2,1,66,10,7,2,3,0,8,3,0,180,11,5,9,8,3,2,1,5,10,6,6,4,47,10,6,0,48,13,16,252,236,252,236,17,23,57,49,0,47,60,236,50,196,17,23,57,48,75,83,88,7,16,5,201,7,16,4,201,7,16,4,201,7,16,5,201,89,34,178,15,10,1,0,93,64,36,5,8,10,9,23,1,24,3,23,8,24,9,38,1, +41,3,38,8,41,9,54,1,57,3,54,8,56,9,14,15,7,15,7,15,10,3,93,1,93,19,33,9,1,33,17,35,17,1,35,1,17,35,86,1,14,1,2,1,4,1,15,187,254,246,153,254,245,186,5,213,253,8,2,248,250,43,5,39,252,237,3,19,250,217,0,1,0,139,0,0,4,70,5,213,0,9,0,109,64,28,7,1,2,1,2, +6,7,6,66,7,2,3,0,180,8,5,6,1,7,2,17,4,49,7,17,0,48,10,16,252,236,252,236,17,57,57,49,0,47,60,236,50,57,57,48,75,83,88,7,16,4,201,7,16,4,201,89,34,178,23,1,1,1,93,64,38,23,2,24,7,41,2,38,7,56,7,87,2,100,2,106,7,117,2,122,7,10,24,6,38,1,41,6,70,1,73,6, +87,1,103,1,104,6,8,93,0,93,19,33,1,17,51,17,33,1,17,35,139,1,0,1,248,195,255,0,254,8,195,5,213,251,51,4,205,250,43,4,205,251,51,0,2,0,117,255,227,4,92,5,240,0,11,0,23,0,35,64,19,9,151,15,3,151,21,150,15,153,24,0,50,12,54,6,50,18,53,24,16,252,236,252, +236,49,0,16,228,244,236,16,238,48,1,16,2,35,34,2,17,16,18,51,50,18,19,16,2,35,34,2,17,16,18,51,50,18,3,137,135,154,153,135,135,153,154,135,211,247,253,253,246,247,252,253,247,2,233,1,73,1,26,254,230,254,183,254,184,254,230,1,25,1,73,254,122,254,128,1, +126,1,136,1,135,1,128,254,128,0,0,0,2,0,197,0,0,4,117,5,213,0,8,0,19,0,43,64,24,1,151,16,0,151,9,136,18,16,10,8,2,4,0,5,50,13,56,17,0,30,9,51,20,16,252,236,50,252,236,17,23,57,49,0,47,244,236,212,236,48,1,17,51,50,54,53,52,38,35,37,33,50,4,21,20,4,43, +1,17,35,1,143,234,140,157,156,141,254,76,1,180,250,1,2,254,255,251,234,202,5,47,253,207,148,133,133,147,166,227,219,221,226,253,168,0,0,0,0,2,0,117,254,242,4,92,5,240,0,17,0,29,0,61,64,32,0,30,16,17,15,27,151,3,21,151,9,150,3,153,17,30,17,24,16,12,15, +0,24,18,50,12,54,24,50,6,53,30,16,252,236,252,236,17,57,57,17,57,17,57,49,0,16,196,228,244,236,16,238,57,18,57,18,57,48,5,34,6,35,34,2,17,16,18,51,50,18,17,16,2,7,23,7,19,16,2,35,34,2,17,16,18,51,50,18,2,143,7,26,8,250,247,247,252,253,247,137,139,200, +151,16,135,154,153,135,135,153,154,135,27,2,1,128,1,134,1,135,1,128,254,128,254,121,254,218,254,153,72,190,100,3,247,1,73,1,26,254,230,254,183,254,184,254,230,1,25,0,2,0,143,0,0,4,209,5,213,0,19,0,28,0,106,64,56,9,8,7,3,10,6,37,3,4,3,5,37,4,4,3,66,6, +4,0,21,3,4,21,151,9,20,151,13,136,11,4,5,17,22,9,6,3,10,3,17,0,28,14,3,10,25,50,4,17,49,20,10,30,12,48,29,16,252,236,50,252,196,236,17,23,57,17,57,17,23,57,17,57,49,0,47,60,244,236,212,236,18,57,18,57,18,57,48,75,83,88,7,16,5,237,7,16,14,237,17,23,57, +89,34,1,30,1,23,19,35,3,46,1,43,1,17,35,17,33,50,4,21,20,6,1,17,51,50,54,53,52,38,35,2,248,78,110,82,203,217,178,77,123,99,193,203,1,160,246,1,6,161,253,208,221,145,142,151,144,2,193,20,111,166,254,104,1,121,161,93,253,137,5,213,222,210,148,187,2,89, +253,238,130,134,129,137,0,1,0,139,255,227,4,74,5,240,0,39,0,132,64,61,13,12,2,14,11,37,30,31,30,8,9,2,7,10,37,31,31,30,66,10,11,30,31,4,1,21,179,20,167,24,151,17,1,179,0,167,4,151,37,150,17,153,40,30,10,11,31,27,7,0,38,27,57,14,49,20,7,57,34,48,40,16, +252,236,196,252,236,228,17,18,57,57,57,57,49,0,16,228,244,236,244,236,16,238,246,238,17,23,57,48,75,83,88,7,16,14,237,17,23,57,7,16,14,237,17,23,57,89,34,178,8,2,1,1,93,64,10,7,0,7,1,7,2,3,7,2,1,93,0,93,1,21,46,1,35,34,6,21,20,22,31,1,30,1,21,20,4,35, +34,38,39,53,30,1,51,50,54,53,52,38,47,1,46,1,53,52,36,51,50,22,3,244,92,185,94,143,166,109,149,106,210,192,254,248,252,105,212,107,115,205,104,153,170,117,145,108,208,188,1,13,223,86,190,5,162,205,59,60,133,113,99,104,35,24,49,210,181,213,224,45,45,215, +73,68,137,123,112,118,32,25,47,190,160,200,241,39,0,1,0,47,0,0,4,162,5,213,0,7,0,28,64,14,6,2,151,0,136,4,1,58,3,30,0,58,5,8,16,212,236,252,236,49,0,47,244,236,50,48,19,33,21,33,17,35,17,33,47,4,115,254,45,203,254,43,5,213,170,250,213,5,43,0,0,0,0,1, +0,147,255,227,4,61,5,213,0,29,0,41,64,23,15,3,18,0,4,1,9,151,24,153,16,1,136,30,15,30,17,49,2,30,0,48,30,16,252,236,252,236,49,0,16,228,50,244,236,17,23,57,48,19,17,51,17,20,22,23,30,1,51,50,54,55,62,1,53,17,51,17,20,6,7,14,1,35,34,38,39,46,1,147,203, +12,15,32,121,86,87,120,33,15,12,202,57,70,66,170,106,105,170,67,69,58,2,61,3,152,252,12,109,93,25,59,60,60,59,25,92,108,3,246,252,104,229,193,63,59,58,58,59,62,197,0,0,0,0,1,0,57,0,0,4,152,5,213,0,6,0,76,64,41,1,37,2,3,2,0,37,6,0,3,3,2,0,37,1,0,4,5,4, +6,37,5,5,4,66,0,5,1,180,3,6,4,3,1,0,5,2,47,5,48,7,16,252,236,23,57,49,0,47,236,50,57,48,75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,89,34,37,1,51,1,35,1,51,2,104,1,95,209,254,75,245,254,75,209,170,5,43,250,43,5,213,0,0,1,0,0,0,0,4,209,5,213, +0,12,0,225,64,68,5,6,5,9,10,9,4,10,9,3,10,11,10,2,1,2,11,11,10,6,37,7,8,7,5,37,4,5,8,8,7,2,37,3,2,12,0,12,1,37,0,12,66,10,5,2,3,8,3,6,0,180,11,8,12,11,10,9,8,6,5,4,3,2,1,11,7,0,47,204,23,57,49,0,47,60,252,60,196,17,23,57,48,75,83,88,7,5,237,7,16,8,237, +7,16,8,237,7,16,5,237,7,16,8,201,7,16,5,201,7,5,201,7,16,8,201,89,34,178,24,9,1,1,93,64,94,31,3,31,4,31,10,47,3,47,4,43,10,63,3,63,4,56,10,90,2,90,5,11,23,11,38,2,42,3,37,4,42,5,40,8,43,9,37,11,38,12,53,2,58,3,53,4,58,5,59,8,58,9,52,11,54,12,84,0,84, +1,90,2,88,3,87,4,86,5,91,6,91,7,82,8,87,9,88,11,93,12,103,8,104,12,121,3,118,4,121,9,118,11,35,93,0,93,17,51,27,1,51,27,1,51,3,35,11,1,35,197,143,170,211,172,143,197,223,191,203,202,191,5,213,251,68,3,34,252,220,4,190,250,43,3,119,252,137,0,1,0,18,0, +0,4,190,5,213,0,11,0,198,64,75,9,37,10,11,10,8,37,7,8,11,11,10,8,37,9,8,5,6,5,7,37,6,6,5,3,37,4,5,4,2,37,1,2,5,5,4,2,37,3,2,11,0,11,1,37,0,0,11,66,11,8,5,2,4,3,0,180,9,6,11,8,7,5,2,5,0,4,59,6,47,0,59,10,48,12,16,252,228,252,228,17,23,57,49,0,47,60,236, +50,23,57,48,75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,89,34,178,55,2,1,0,93,64,56,13,5,4,11,24,5,39,1,40,3,41,5,38,11,88,11,120,2,121,5,119,11,11,0,2,0,2,15,8,15,8,20,2,26,8,33,2,37,5,43,8,37,11, +53,2,85,2,89,8,88,11,101,2,115,2,16,93,1,93,19,51,9,1,51,9,1,35,9,1,35,1,86,217,1,72,1,78,217,254,65,1,223,217,254,146,254,117,218,1,244,5,213,253,205,2,51,253,66,252,233,2,131,253,125,3,23,0,0,1,0,37,0,0,4,172,5,213,0,8,0,89,64,46,3,37,4,5,4,2,37,1, +2,5,5,4,2,37,3,2,8,0,8,1,37,0,0,8,66,2,3,0,180,6,2,7,3,5,4,1,7,0,4,60,5,30,0,60,7,9,16,212,236,252,236,17,18,57,17,18,57,17,57,49,0,47,236,50,57,48,75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,89,34,19,51,9,1,51,1,17,35,17,37,215,1,108,1,107, +217,254,33,203,5,213,253,109,2,147,252,201,253,98,2,158,0,0,0,1,0,156,0,0,4,145,5,213,0,9,0,69,64,28,8,37,2,3,2,3,37,7,8,7,66,8,151,0,136,3,151,5,8,3,0,1,4,47,0,6,48,10,16,252,196,252,196,17,57,57,49,0,47,236,244,236,48,75,83,88,7,16,5,237,7,16,5,237, +89,34,178,8,8,1,1,93,178,7,3,1,93,19,33,21,1,33,21,33,53,1,33,178,3,201,252,244,3,34,252,11,2,247,253,31,5,213,154,251,111,170,154,4,145,0,0,1,1,207,254,242,3,119,6,20,0,7,0,30,64,15,4,182,6,183,2,182,0,181,8,5,1,3,61,0,8,16,212,252,196,50,49,0,16,252, +236,244,236,48,1,33,21,35,17,51,21,33,1,207,1,168,240,240,254,88,6,20,143,249,252,143,0,0,0,1,0,102,255,66,4,55,5,213,0,3,0,24,64,11,1,0,136,4,1,30,2,0,30,3,4,16,212,236,212,236,49,0,16,244,196,48,9,1,35,1,1,37,3,18,190,252,237,5,213,249,109,6,147,0, +0,1,1,90,254,242,3,2,6,20,0,7,0,30,64,15,3,182,1,183,5,182,0,181,8,0,61,6,2,4,8,16,212,196,50,236,49,0,16,252,236,244,236,48,1,17,33,53,51,17,35,53,3,2,254,88,240,240,6,20,248,222,143,6,4,143,0,0,0,1,0,72,3,168,4,137,5,213,0,6,0,24,64,10,3,4,1,0,136, +7,3,1,5,7,16,212,204,57,49,0,16,244,204,50,57,48,9,1,35,9,1,35,1,2,193,1,200,178,254,145,254,146,178,1,200,5,213,253,211,1,139,254,117,2,45,0,0,1,0,0,254,29,4,209,254,109,0,3,0,15,181,0,184,1,4,0,2,47,204,49,0,16,212,236,48,1,21,33,53,4,209,251,47,254, +109,80,80,0,0,0,0,1,1,23,4,238,2,246,6,102,0,3,0,37,64,9,1,186,0,185,4,1,60,3,4,16,212,236,49,0,16,244,75,176,9,84,75,176,14,84,91,88,185,0,0,0,64,56,89,236,48,9,1,35,1,1,221,1,25,154,254,187,6,102,254,136,1,120,0,2,0,133,255,227,4,35,4,123,0,11,0,41, +0,110,64,42,10,7,0,26,32,12,24,15,7,0,182,24,7,140,18,33,139,32,191,29,140,36,190,18,153,24,13,1,24,4,25,14,10,6,12,68,32,4,6,21,62,42,16,244,236,196,252,236,50,50,17,57,57,49,0,47,196,228,244,252,244,236,16,238,16,238,17,57,17,57,18,57,17,18,57,48,64, +29,48,31,48,32,48,33,48,34,160,0,160,1,160,2,160,10,160,11,162,22,160,23,160,24,160,25,160,26,14,93,1,35,34,6,21,20,22,51,50,54,55,53,55,17,35,53,14,1,35,34,38,53,52,54,59,1,53,46,1,35,34,6,7,53,62,1,51,50,22,23,30,1,2,190,61,161,163,122,108,152,174, +1,185,185,59,179,128,171,204,251,243,247,1,134,147,94,192,91,102,187,88,139,197,61,38,32,2,51,113,112,101,112,211,186,41,76,253,129,166,100,95,193,162,187,194,29,134,121,54,52,184,39,39,82,82,50,147,0,0,0,0,2,0,193,255,227,4,88,6,20,0,11,0,28,0,48,64, +26,24,12,9,3,140,15,9,140,21,153,15,190,27,155,25,0,18,18,71,24,12,6,6,26,70,29,16,244,236,50,50,252,236,49,0,47,236,228,244,236,16,238,17,57,57,48,1,52,38,35,34,6,21,20,22,51,50,54,1,62,1,51,50,18,17,16,2,35,34,38,39,21,35,17,51,3,150,136,133,134,138, +138,134,133,136,253,227,44,155,102,202,232,233,203,100,153,46,184,184,2,47,214,218,219,213,212,220,218,2,120,82,88,254,201,254,239,254,235,254,197,87,83,141,6,20,0,0,1,0,195,255,227,4,37,4,123,0,25,0,47,64,26,12,139,13,192,16,0,139,25,192,22,140,3,16, +140,9,190,3,153,26,19,18,12,0,6,70,26,16,244,196,50,236,49,0,16,228,244,236,16,254,244,238,16,245,238,48,37,14,1,35,32,0,17,16,0,33,50,22,23,21,46,1,35,34,6,21,20,22,51,50,54,55,4,37,74,157,82,254,252,254,219,1,37,1,4,81,154,78,73,147,93,173,186,187, +172,96,152,65,57,43,43,1,56,1,20,1,20,1,56,42,44,193,65,58,224,208,207,225,59,62,0,0,2,0,123,255,227,4,18,6,20,0,16,0,28,0,48,64,26,5,0,20,26,140,14,20,140,8,153,14,190,1,155,3,23,4,0,6,2,71,17,18,11,72,29,16,244,236,252,236,50,50,49,0,47,236,228,244, +236,16,238,17,57,57,48,1,17,51,17,35,53,14,1,35,34,2,17,16,18,51,50,22,1,20,22,51,50,54,53,52,38,35,34,6,3,90,184,184,46,153,100,203,233,234,202,101,154,254,15,136,133,133,139,139,133,133,136,3,209,2,67,249,236,141,83,87,1,59,1,21,1,17,1,55,87,254,11, +214,218,220,212,213,219,218,0,0,2,0,123,255,227,4,88,4,123,0,21,0,28,0,69,64,38,0,22,3,1,10,139,9,141,6,22,182,1,6,140,13,1,193,25,140,19,190,13,153,29,3,2,28,16,9,22,6,0,73,28,18,16,72,29,16,244,236,252,236,196,17,18,57,57,49,0,16,228,244,236,228,16, +238,16,238,16,244,238,18,57,17,57,48,1,21,33,21,20,22,51,50,54,55,21,14,1,35,32,0,17,16,0,51,50,18,7,46,1,35,34,6,7,4,88,252,227,191,174,88,192,109,105,195,91,254,251,254,218,1,32,240,214,247,184,4,145,136,133,172,16,2,94,90,6,183,200,56,57,183,43,43, +1,57,1,19,1,12,1,64,254,222,197,162,169,176,156,0,1,0,195,0,0,4,39,6,20,0,19,0,52,64,26,5,16,1,12,8,182,6,1,140,0,155,14,6,194,10,2,19,7,0,9,5,6,13,15,11,20,16,212,60,196,252,60,196,50,57,57,49,0,47,228,50,252,236,16,238,50,18,57,57,48,1,21,35,34,6,29, +1,33,21,33,17,35,17,33,53,33,53,52,54,51,4,39,209,99,77,1,129,254,127,184,254,213,1,43,169,179,6,20,153,81,103,99,143,252,47,3,209,143,78,184,174,0,0,0,0,2,0,123,254,72,4,18,4,123,0,11,0,41,0,72,64,39,25,12,30,27,39,9,3,18,139,19,22,9,140,30,22,140,15, +3,140,36,190,30,15,195,40,194,42,39,25,0,6,12,71,6,18,18,33,72,42,16,244,196,236,252,236,50,50,49,0,16,228,228,196,244,236,16,238,16,238,16,213,238,17,18,57,57,17,57,57,48,1,52,38,35,34,6,21,20,22,51,50,54,19,20,2,35,34,38,39,53,30,1,51,50,54,61,2,14, +1,35,34,2,17,16,18,51,50,22,23,53,51,3,90,135,129,135,142,143,136,127,135,184,238,231,76,166,83,98,160,67,149,136,44,152,109,196,234,234,196,108,150,47,184,2,57,207,215,215,207,207,217,218,254,221,252,254,252,28,27,182,46,44,162,176,8,125,94,92,1,58, +1,7,1,8,1,58,86,90,145,0,0,0,0,1,0,195,0,0,4,27,6,20,0,19,0,44,64,24,9,14,3,0,3,1,6,140,17,190,12,155,10,1,2,6,0,74,13,9,6,11,70,20,16,244,236,50,252,236,49,0,47,60,236,244,236,17,23,57,57,48,1,17,35,17,52,38,35,34,6,21,17,35,17,51,17,62,1,51,50,22,4, +27,185,106,113,129,139,184,184,49,168,115,171,169,2,182,253,74,2,182,151,142,183,171,253,135,6,20,253,164,96,99,225,0,0,2,0,178,0,0,4,68,6,20,0,9,0,13,0,46,64,25,8,182,0,12,196,10,155,0,194,6,2,182,4,3,76,11,1,6,5,76,0,75,10,7,14,16,212,60,228,236,252, +60,236,49,0,47,236,50,228,252,236,16,238,48,1,33,17,33,21,33,53,33,17,33,1,51,21,35,1,0,1,215,1,109,252,110,1,109,254,225,1,31,184,184,4,96,252,47,143,143,3,66,2,67,233,0,0,2,0,186,254,86,3,16,6,20,0,13,0,17,0,56,64,29,5,0,1,10,140,8,1,182,3,16,196,14, +155,3,194,8,195,18,11,8,2,9,2,15,4,6,14,0,18,16,212,60,236,50,196,196,18,57,57,49,0,16,228,228,252,236,16,238,16,238,17,57,57,48,5,17,33,53,33,17,20,6,43,1,53,51,50,54,17,51,21,35,2,88,254,195,1,245,179,165,254,234,90,90,184,184,20,3,229,143,251,140, +195,211,156,125,6,165,233,0,0,0,0,1,0,236,0,0,4,178,6,20,0,11,0,197,64,58,8,23,9,8,5,6,5,7,23,6,6,5,9,23,3,2,8,23,7,8,3,2,5,23,6,5,2,3,2,4,23,3,3,2,66,8,5,2,3,3,194,0,155,10,6,8,5,4,3,6,9,1,6,6,68,0,69,12,16,244,236,236,50,17,23,57,49,0,47,60,236,228, +23,57,48,75,83,88,7,16,5,237,7,16,8,237,7,8,237,7,4,237,7,16,5,237,7,16,8,237,89,34,178,8,7,1,1,93,64,82,6,2,8,8,22,2,24,5,24,8,53,2,52,5,54,8,70,2,102,2,117,2,118,5,12,9,3,8,8,25,3,23,4,24,5,25,6,26,7,24,8,40,3,39,5,40,7,59,3,59,4,55,5,57,7,55,8,74, +3,73,7,89,6,89,7,107,3,105,4,105,6,105,7,121,3,120,5,121,6,121,7,28,93,0,93,19,51,17,1,51,9,1,35,1,7,17,35,236,190,1,227,224,254,71,1,254,225,254,98,137,190,6,20,252,123,1,209,254,90,253,70,2,66,129,254,63,0,1,0,160,0,0,4,10,6,31,0,13,0,38,64,19,9,0, +3,10,182,12,197,3,182,5,3,6,4,0,6,11,76,9,14,16,212,236,252,204,57,57,49,0,47,236,252,236,17,57,57,48,1,20,22,59,1,21,35,34,38,53,17,33,53,33,2,127,91,89,215,233,165,181,254,217,1,223,1,150,124,126,156,212,194,3,249,144,0,1,0,109,0,0,4,111,4,123,0,34, +0,163,64,39,24,18,15,9,4,7,0,29,27,6,7,21,12,140,32,3,190,27,194,25,16,7,0,17,15,8,77,6,78,17,77,15,78,28,24,77,26,69,35,16,244,75,176,12,84,75,176,17,84,91,88,185,0,26,255,192,56,89,252,60,252,236,252,236,17,18,57,49,0,47,60,60,228,244,60,236,50,17, +57,17,57,57,17,23,57,48,64,71,48,4,48,5,48,6,48,7,48,8,48,9,48,10,48,11,63,22,63,23,63,24,63,25,63,26,63,27,63,28,63,29,63,30,128,3,128,4,128,5,128,6,128,7,128,8,128,9,128,10,128,11,143,22,143,23,143,24,143,25,143,26,143,27,143,28,143,29,143,30,35,1, +93,1,62,1,51,50,22,25,1,35,17,52,38,35,34,6,21,17,35,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,22,2,164,34,105,74,135,111,168,53,70,80,59,168,57,74,73,57,167,167,33,99,63,76,101,3,238,72,69,209,254,223,253,119,2,129,237,115,123,229,253,127,2,129, +240,112,123,229,253,127,4,96,96,60,63,70,0,0,1,0,195,0,0,4,27,4,123,0,19,0,44,64,24,9,14,3,0,3,1,6,140,17,190,12,194,10,1,2,6,0,74,13,9,6,11,70,20,16,244,236,50,252,236,49,0,47,60,228,244,236,17,23,57,57,48,1,17,35,17,52,38,35,34,6,21,17,35,17,51,21, +62,1,51,50,22,4,27,185,106,113,129,139,184,184,49,168,115,171,169,2,182,253,74,2,182,151,142,183,171,253,135,4,96,168,96,99,225,0,0,0,2,0,137,255,227,4,72,4,123,0,11,0,23,0,35,64,19,6,140,18,0,140,12,190,18,153,24,9,18,15,68,3,18,21,62,24,16,244,236, +252,236,49,0,16,228,244,236,16,238,48,1,34,6,21,20,22,51,50,54,53,52,38,39,50,18,17,16,2,35,34,2,17,16,18,2,104,140,144,144,140,141,144,144,141,233,247,246,234,233,246,246,3,223,218,214,213,219,219,213,214,218,156,254,210,254,226,254,225,254,211,1,45, +1,31,1,30,1,46,0,0,2,0,190,254,86,4,84,4,123,0,16,0,28,0,51,64,28,5,0,20,26,140,14,20,140,8,190,14,153,1,195,3,194,29,17,18,11,71,23,4,0,6,2,70,29,16,244,236,50,50,252,236,49,0,16,228,228,228,244,236,16,238,17,57,57,48,37,17,35,17,51,21,62,1,51,50,18, +17,16,2,35,34,38,1,52,38,35,34,6,21,20,22,51,50,54,1,119,185,185,46,153,100,203,231,232,202,102,153,1,240,135,133,134,138,138,134,133,135,141,253,201,6,10,143,83,87,254,198,254,234,254,239,254,201,87,1,245,214,218,219,213,212,220,218,0,0,0,0,2,0,137, +254,82,4,31,4,119,0,11,0,28,0,51,64,28,24,12,9,3,140,15,9,140,21,190,15,153,27,195,25,194,29,24,12,6,6,26,71,0,18,18,62,29,16,244,236,252,236,50,50,49,0,16,228,228,228,244,236,16,238,17,57,57,48,1,20,22,51,50,54,53,52,38,35,34,6,1,14,1,35,34,2,17,16, +18,51,50,22,23,53,51,17,35,1,76,135,133,133,137,137,133,133,135,2,26,45,153,101,201,233,232,202,100,153,46,185,185,2,43,214,218,219,213,213,219,218,253,138,83,89,1,55,1,17,1,22,1,58,87,83,143,249,246,0,0,0,1,1,106,0,0,4,131,4,123,0,17,0,79,64,19,6,7, +11,3,0,17,3,151,14,190,9,194,7,10,6,6,0,8,18,16,212,196,236,50,49,0,47,228,244,236,212,204,17,57,17,57,48,64,37,16,0,16,1,16,17,32,0,32,1,32,17,48,0,48,1,51,16,48,17,64,0,64,1,67,16,64,17,80,0,80,1,80,16,80,17,18,93,1,46,1,35,34,6,21,17,35,17,51,21,62, +1,51,50,22,23,4,131,59,122,73,172,182,185,185,46,191,131,68,118,54,3,121,46,42,216,204,253,211,4,96,219,119,127,34,36,0,0,0,0,1,0,213,255,227,4,6,4,123,0,39,0,117,64,64,13,12,2,14,11,23,31,30,8,9,2,7,10,23,30,31,30,66,29,30,24,10,11,30,31,4,21,0,139, +1,192,4,20,139,21,192,24,140,17,4,140,37,190,17,153,40,29,10,11,31,27,7,0,79,27,6,14,73,7,6,20,34,69,40,16,244,196,236,252,236,228,17,18,57,57,57,57,49,0,16,228,244,236,16,254,245,238,16,245,238,18,23,57,17,18,57,48,75,83,88,7,16,14,237,17,23,57,7,14, +237,17,23,57,89,34,1,21,46,1,35,34,6,21,20,22,31,1,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,47,2,46,1,53,52,54,51,50,22,3,205,79,160,83,125,123,92,183,74,137,141,236,210,83,182,106,103,188,84,122,134,245,8,69,159,146,218,202,90,166,4,57,180,46, +46,81,83,75,74,35,14,26,156,125,166,187,35,35,190,53,53,99,89,128,49,2,14,31,147,127,161,175,33,0,0,0,1,0,131,0,0,4,8,5,158,0,19,0,49,64,24,14,5,8,15,3,182,0,17,1,194,8,182,10,8,11,9,2,4,0,6,16,18,14,20,16,212,60,196,252,60,196,50,57,57,49,0,47,236,244, +60,196,236,50,17,57,57,48,1,17,33,21,33,17,20,22,59,1,21,35,34,38,53,17,33,53,33,17,2,102,1,162,254,94,94,117,207,225,207,170,254,213,1,43,5,158,254,194,143,253,160,124,98,147,166,203,2,96,143,1,62,0,1,0,195,255,227,4,27,4,94,0,19,0,44,64,24,9,14,3,0, +3,1,6,140,17,153,10,1,194,12,13,9,6,11,74,2,6,0,70,20,16,244,236,252,236,50,49,0,47,228,50,244,236,17,23,57,57,48,19,17,51,17,20,22,51,50,54,53,17,51,17,35,53,14,1,35,34,38,195,184,107,112,130,138,185,185,49,169,113,172,168,1,168,2,182,253,74,151,142, +183,171,2,121,251,162,168,97,100,225,0,0,0,0,1,0,100,0,0,4,109,4,96,0,6,0,101,64,41,3,23,4,5,4,2,23,1,2,5,5,4,2,23,3,2,6,0,6,1,23,0,0,6,66,2,3,0,194,5,6,5,3,2,1,5,4,73,0,69,7,16,244,236,23,57,49,0,47,228,50,57,48,75,83,88,7,16,5,237,7,16,8,237,7,16,8, +237,7,16,5,237,89,34,178,39,2,1,0,93,64,14,7,0,7,1,8,3,8,4,4,5,2,37,2,2,93,1,93,19,51,9,1,51,1,35,100,191,1,69,1,70,191,254,114,237,4,96,252,84,3,172,251,160,0,1,0,0,0,0,4,209,4,96,0,12,1,17,64,69,11,2,3,2,10,9,10,3,3,2,10,11,10,4,5,4,9,5,5,4,6,23,7, +8,7,5,23,4,5,8,8,7,2,23,3,2,12,0,12,1,23,0,12,66,10,5,2,3,8,3,6,0,194,11,8,12,11,10,9,8,6,5,4,3,2,1,11,7,0,47,204,23,57,49,0,47,60,244,60,196,17,23,57,48,75,83,88,7,5,237,7,16,8,237,7,16,8,237,7,16,5,237,7,16,5,201,7,16,8,201,7,16,8,201,7,16,5,201,89, +34,178,15,10,1,0,93,64,140,11,9,4,11,31,0,31,1,29,2,26,3,28,4,25,5,28,9,27,10,26,11,31,12,38,0,38,1,41,2,38,5,41,6,41,7,35,8,44,12,57,2,54,5,57,6,57,7,51,8,60,12,69,8,73,9,70,11,74,12,86,8,88,9,87,11,89,12,102,2,105,3,102,4,105,5,106,9,101,11,118,2,122, +5,120,8,124,9,114,11,45,15,10,25,2,31,3,31,4,25,5,31,10,31,10,43,2,43,5,62,2,62,5,60,10,72,10,89,10,106,2,105,5,104,10,123,2,127,3,121,4,127,4,122,5,124,10,127,10,24,93,1,93,17,51,27,1,51,27,1,51,1,35,11,1,35,182,195,160,157,162,195,182,254,250,176,179, +178,176,4,96,252,119,2,66,253,190,3,137,251,160,2,102,253,154,0,0,0,0,1,0,76,0,0,4,133,4,96,0,11,0,169,64,72,5,23,6,7,6,4,23,3,4,7,7,6,4,23,5,4,1,2,1,3,23,2,2,1,11,23,0,1,0,10,23,9,10,1,1,0,10,23,11,10,7,8,7,9,23,8,8,7,66,10,7,4,1,4,8,0,194,5,2,10,7, +4,1,4,8,0,2,73,8,6,69,12,16,244,196,252,196,17,23,57,49,0,47,60,228,50,23,57,48,75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,89,34,178,7,10,1,0,93,64,30,9,1,6,7,102,1,105,7,118,1,121,7,6,7,1,7,7,6,10, +21,10,58,4,52,10,90,4,86,10,8,93,1,93,9,2,35,9,1,35,9,1,51,9,1,4,94,254,111,1,184,213,254,184,254,185,213,1,184,254,111,204,1,41,1,39,4,96,253,232,253,184,1,193,254,63,2,72,2,24,254,107,1,149,0,0,0,0,1,0,104,254,86,4,129,4,96,0,18,0,160,64,69,13,23,14, +13,2,3,2,10,11,2,9,12,23,3,3,2,17,23,18,0,18,16,23,15,16,0,0,18,16,23,17,16,13,14,13,15,23,14,14,13,66,16,19,13,0,14,9,140,7,195,17,14,194,19,17,16,15,13,10,7,0,7,18,8,18,73,14,69,19,16,244,236,196,17,23,57,49,0,16,228,50,244,236,17,57,57,18,57,48,75, +83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,7,16,5,237,17,23,57,7,16,8,237,89,34,178,56,18,1,1,93,64,26,4,16,118,16,2,8,17,8,18,25,12,25,13,38,14,38,15,56,17,73,17,73,18,89,13,10,93,0,93,1,6,7,2,7,14,1,43,1,53,51,50,54,55,1,51,9,1,51,3,90,46,71, +99,34,46,138,92,148,109,81,92,71,254,79,195,1,76,1,71,195,1,104,117,191,254,248,58,78,78,154,94,196,4,78,252,148,3,108,0,0,0,0,1,0,203,0,0,4,16,4,98,0,9,0,88,64,28,3,23,7,8,7,8,23,2,3,2,66,8,182,0,194,3,182,5,8,3,0,4,1,73,0,6,69,10,16,244,196,236,50, +17,57,57,49,0,47,236,244,236,48,75,83,88,7,16,5,237,7,16,5,237,89,34,178,56,8,1,1,93,64,21,54,3,56,8,69,3,74,8,87,3,88,8,101,3,106,8,117,3,122,8,10,93,19,33,21,1,33,21,33,53,1,33,227,3,45,253,125,2,131,252,187,2,131,253,149,4,98,168,252,220,150,170,3, +37,0,0,0,1,0,221,254,178,3,244,6,20,0,36,0,102,64,53,25,15,21,11,6,37,9,26,16,21,29,11,5,32,33,3,0,11,182,9,0,182,1,198,9,199,21,182,19,181,37,12,9,10,5,36,22,25,0,29,10,5,19,2,20,0,32,25,61,10,15,5,37,16,212,60,196,252,60,196,50,57,57,17,18,57,17,18, +57,57,17,18,57,57,49,0,16,252,236,228,244,236,16,238,18,23,57,18,57,17,57,57,17,18,57,17,18,57,57,48,5,21,35,34,38,61,1,52,38,43,1,53,51,50,54,61,1,52,54,59,1,21,35,34,6,29,1,20,6,7,30,1,29,1,20,22,51,3,244,64,249,169,107,140,62,62,141,106,169,249,64, +70,140,85,91,110,111,90,85,140,190,144,148,221,239,151,116,143,114,150,240,221,147,143,87,142,248,157,142,25,27,142,156,248,143,86,0,0,0,1,2,18,254,29,2,190,6,29,0,3,0,18,183,1,0,181,4,0,4,2,4,16,212,236,49,0,16,252,204,48,1,17,35,17,2,190,172,6,29,248, +0,8,0,0,0,0,0,1,0,221,254,178,3,244,6,20,0,36,0,106,64,55,31,37,27,22,12,15,8,27,11,21,25,15,4,5,32,3,0,25,182,27,0,182,35,198,27,199,15,182,17,181,37,28,25,26,21,15,1,4,0,8,26,21,35,18,4,0,26,31,21,61,16,0,11,4,37,16,212,60,196,50,252,60,196,17,18,57, +57,17,18,57,17,18,57,57,17,18,57,57,49,0,16,252,236,228,244,236,16,238,18,23,57,17,18,57,57,17,57,17,57,57,17,18,57,48,23,51,50,54,61,1,52,54,55,46,1,61,1,52,38,43,1,53,51,50,22,29,1,20,22,59,1,21,35,34,6,29,1,20,6,43,1,221,68,141,86,90,111,110,91,86, +141,68,62,249,168,107,141,64,64,141,107,168,249,62,190,88,141,248,156,142,27,25,142,157,248,141,88,143,147,221,240,150,114,143,116,151,239,221,148,0,0,0,0,1,0,88,1,236,4,121,3,12,0,27,0,38,64,18,1,11,4,15,0,14,4,160,25,18,0,160,11,28,0,14,39,28,16,252, +196,49,0,16,212,252,60,212,236,50,18,57,17,18,57,48,1,21,14,1,35,34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,22,23,22,23,22,51,50,54,4,121,75,143,79,90,113,22,11,77,103,51,79,141,73,78,146,83,53,100,74,12,21,116,93,70,137,3,12,174,59,55,51,10,4,33,24,59, +63,174,60,54,22,31,5,10,55,61,0,2,2,4,254,139,2,207,4,96,0,3,0,9,0,33,64,16,6,0,134,4,136,1,194,10,7,6,8,2,3,4,0,10,16,212,60,236,50,57,57,49,0,16,244,228,252,204,48,1,53,51,21,3,17,19,51,19,17,2,4,203,203,21,161,21,3,98,254,254,251,41,2,143,1,101,254, +155,253,113,0,2,0,213,254,199,4,37,5,152,0,26,0,33,0,78,64,42,27,8,5,4,28,0,139,1,141,28,9,139,8,141,5,203,12,28,203,22,24,21,190,15,12,153,13,34,27,21,14,7,23,12,4,8,0,31,30,18,69,34,16,244,236,212,60,212,60,60,236,50,50,49,0,16,196,228,50,244,60,196, +236,16,254,244,238,16,245,238,17,57,17,18,57,48,1,21,46,1,39,17,62,1,55,21,14,1,7,17,35,17,38,0,53,52,0,55,17,51,17,30,1,1,17,14,1,21,20,22,4,37,67,130,63,63,131,66,73,130,57,103,225,254,252,1,7,222,103,57,130,254,222,132,160,160,4,53,172,40,44,4,252, +154,5,45,40,172,31,34,3,254,226,1,30,22,1,57,251,250,1,61,19,1,31,254,225,3,34,252,43,3,96,12,236,184,184,235,0,1,0,139,0,0,4,88,5,240,0,27,0,62,64,32,7,22,1,18,10,182,20,8,12,1,139,0,167,4,151,25,150,16,12,151,14,0,13,9,11,7,30,15,19,21,17,28,16,212, +60,196,196,252,60,196,212,196,49,0,47,236,50,244,236,244,236,16,212,60,238,50,18,57,57,48,1,21,46,1,35,34,6,29,1,33,21,33,17,33,21,33,53,51,17,35,53,51,53,52,54,51,50,22,4,68,62,127,67,134,127,1,115,254,141,2,25,252,51,236,199,199,219,223,65,137,5,182, +184,44,44,179,192,217,143,254,47,170,170,1,209,143,238,254,250,29,0,0,0,2,0,205,0,195,4,76,4,66,0,11,0,47,0,129,64,26,32,22,27,23,14,40,45,13,24,30,27,9,42,12,45,39,33,21,15,4,3,9,255,31,23,27,184,1,0,64,39,3,255,41,13,45,48,31,41,36,32,13,23,18,14,33, +39,36,6,15,21,18,42,30,24,12,4,6,0,120,22,14,18,121,6,120,40,32,36,48,16,212,196,50,236,252,196,50,236,17,23,57,17,57,57,17,18,57,57,17,18,57,57,17,18,57,57,49,0,16,212,196,50,236,252,196,50,236,17,23,57,18,57,57,17,18,57,57,17,18,57,57,17,18,57,57,48, +1,52,38,35,34,6,21,20,22,51,50,54,3,55,23,7,30,1,21,20,6,7,23,7,39,14,1,35,34,38,39,7,39,55,46,1,53,52,54,55,39,55,23,62,1,51,50,22,3,100,124,91,90,125,125,90,91,124,24,166,90,166,30,29,30,31,168,94,166,46,91,50,48,96,48,164,92,166,31,29,31,31,168,94, +166,46,91,51,46,94,2,131,90,123,123,90,92,125,126,1,116,166,93,166,49,93,48,50,91,45,166,94,167,31,30,29,28,163,90,166,51,93,46,50,93,45,166,95,168,31,30,29,0,0,0,0,1,0,37,0,0,4,172,5,213,0,24,0,127,64,68,3,37,4,9,4,2,37,1,2,9,9,4,2,37,3,2,20,0,20,1, +37,0,0,20,66,2,7,5,16,12,231,18,10,23,5,231,21,7,3,0,136,14,24,1,17,2,15,8,5,3,3,6,4,60,11,6,101,13,9,30,22,17,101,0,60,19,15,25,16,212,60,236,236,50,252,60,236,50,236,18,23,57,18,57,17,57,57,49,0,47,228,50,212,60,236,50,212,60,236,50,17,18,57,48,75, +83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,89,34,19,51,9,1,51,1,51,21,33,7,21,33,21,33,17,35,17,33,53,33,53,39,33,53,51,37,215,1,108,1,107,217,254,182,252,254,197,86,1,145,254,111,203,254,113,1,143,90,254,203,243,5,213,253,109,2,147,253,207,111, +151,35,111,253,244,2,12,111,35,151,111,0,2,2,18,254,162,2,190,5,152,0,3,0,7,0,33,188,0,5,1,7,0,4,0,0,1,7,183,1,8,4,0,4,6,2,8,16,212,60,236,50,49,0,16,212,236,212,236,48,1,17,35,17,19,17,35,17,2,190,172,172,172,5,152,253,10,2,246,252,0,253,10,2,246,0, +0,0,2,0,199,255,61,4,12,5,240,0,50,0,62,0,106,64,60,35,36,30,57,51,11,17,36,42,4,1,27,143,26,206,30,207,23,1,143,0,206,4,207,48,150,23,63,35,7,17,60,33,42,54,11,36,57,51,4,7,33,85,20,7,85,45,20,60,85,0,38,14,45,26,38,54,85,39,63,16,212,236,228,196,212, +228,236,196,16,238,16,238,17,23,57,18,57,17,18,57,18,57,49,0,16,196,244,236,244,236,16,238,246,238,17,23,57,57,57,17,18,57,48,1,21,46,1,35,34,6,21,20,23,22,23,30,1,21,20,6,7,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,47,1,46,1,53,52,54,55,46,1,53, +52,54,51,50,22,1,14,1,21,20,22,23,62,1,53,52,38,3,168,83,143,57,97,107,205,26,14,212,130,91,93,61,58,204,173,73,155,87,87,148,57,102,113,221,24,214,128,93,91,60,59,200,167,72,153,254,141,62,61,141,247,62,60,143,5,182,164,39,39,80,71,90,115,15,8,119,154, +101,90,140,53,52,109,64,142,168,29,29,164,39,39,84,76,102,123,14,120,153,102,91,143,49,44,112,69,130,159,29,253,213,45,90,47,76,135,133,45,90,47,76,136,0,0,0,0,2,1,63,5,70,3,145,6,16,0,3,0,7,0,29,64,14,6,2,222,4,0,221,8,5,97,4,1,97,0,8,16,212,252,212, +236,49,0,16,244,60,236,50,48,1,51,21,35,37,51,21,35,1,63,203,203,1,136,202,202,6,16,202,202,202,0,0,0,3,0,0,0,125,4,209,5,78,0,25,0,49,0,73,0,68,64,39,13,218,14,10,218,17,220,38,212,62,1,218,0,4,218,23,217,26,212,62,211,50,209,74,7,92,20,13,0,94,44,7, +56,20,32,7,56,89,68,47,230,254,197,16,254,229,50,16,238,49,0,16,244,236,252,244,236,212,236,16,254,253,238,214,238,48,1,21,46,1,35,34,6,21,20,22,51,50,54,55,21,14,1,35,34,38,53,52,54,51,50,22,39,34,6,7,14,1,21,20,22,23,30,1,51,50,54,55,62,1,53,52,38, +39,46,1,39,50,22,23,30,1,21,20,6,7,14,1,35,34,38,39,46,1,53,52,54,55,62,1,3,96,58,111,58,117,135,140,130,56,103,50,52,114,61,180,207,208,179,61,114,196,106,181,75,75,77,77,75,76,181,105,106,181,76,76,75,76,75,75,181,107,127,218,90,90,92,91,91,91,218, +126,125,218,91,91,91,92,90,90,218,4,47,108,28,27,149,128,132,142,25,26,104,23,22,200,172,173,202,22,161,74,75,75,184,106,104,183,75,76,76,76,76,76,181,105,106,184,75,75,74,103,90,90,91,220,126,125,218,91,91,91,91,91,91,218,125,126,220,91,90,90,0,0,0, +3,1,14,1,213,3,193,5,240,0,10,0,37,0,41,0,100,64,54,9,6,0,25,31,11,23,14,6,0,40,243,38,0,237,23,38,241,6,237,12,17,32,239,31,238,28,237,17,240,35,150,42,38,31,20,0,23,9,3,40,39,24,13,9,106,11,107,31,3,106,20,105,42,16,252,236,196,252,236,50,50,192,192, +17,18,57,57,17,18,57,49,0,16,244,228,252,244,236,16,196,238,237,214,238,16,238,17,18,57,18,57,17,57,17,18,57,48,1,34,6,21,20,22,51,50,54,61,1,55,17,35,53,14,1,35,34,38,53,52,54,59,1,53,52,38,35,34,6,7,53,62,1,51,50,22,1,33,21,33,2,172,144,124,87,72,105, +131,143,143,49,131,82,129,150,187,172,182,119,117,51,125,67,68,135,63,184,172,253,107,2,156,253,100,4,80,68,78,64,77,143,115,29,61,254,64,112,65,66,136,116,129,140,4,90,92,35,33,127,28,28,172,253,12,123,0,0,0,0,2,0,119,0,141,4,18,4,35,0,6,0,13,0,47,64, +23,9,2,11,4,252,7,0,172,14,2,12,5,9,0,10,7,118,12,3,0,118,5,14,16,212,252,60,212,236,50,17,57,17,18,57,49,0,16,244,60,236,50,57,57,48,1,21,9,1,21,1,53,1,21,9,1,21,1,53,2,76,254,211,1,45,254,43,3,155,254,211,1,45,254,43,4,35,191,254,244,254,244,191,1, +162,82,1,162,191,254,244,254,244,191,1,162,82,0,0,1,0,88,1,115,4,121,3,94,0,5,0,24,64,11,4,160,2,0,6,3,28,1,0,39,6,16,252,212,236,49,0,16,212,196,236,48,19,33,17,35,17,33,88,4,33,168,252,135,3,94,254,21,1,63,0,1,1,100,1,223,3,109,2,131,0,3,0,17,182,0, +160,2,4,1,0,4,16,212,196,49,0,16,212,236,48,1,33,21,33,1,100,2,9,253,247,2,131,164,0,4,0,0,0,125,4,209,5,78,0,19,0,28,0,52,0,76,0,133,64,73,15,14,13,3,16,12,93,9,10,9,11,93,10,10,9,66,12,10,6,22,9,10,22,215,15,20,215,0,17,10,214,65,212,41,0,213,53,212, +41,211,29,209,77,23,20,15,12,4,0,6,16,9,26,3,21,16,92,18,26,92,10,3,91,71,7,35,18,88,59,7,35,89,47,47,230,254,229,16,254,245,196,238,16,238,50,17,18,57,17,57,57,23,57,49,0,16,244,236,252,228,16,254,237,50,16,238,214,238,18,57,18,57,18,57,48,75,83,88, +7,16,5,237,7,16,4,237,17,23,57,89,34,1,50,22,21,20,6,7,30,1,31,1,35,39,46,1,43,1,17,35,17,23,35,21,51,50,54,53,52,38,3,50,22,23,30,1,21,20,6,7,14,1,35,34,38,39,46,1,53,52,54,55,62,1,23,34,6,7,14,1,21,20,22,23,30,1,51,50,54,55,62,1,53,52,38,39,46,1,2, +88,147,144,88,80,19,58,38,114,143,107,49,61,45,55,130,232,102,102,90,74,74,68,127,218,90,90,92,91,91,91,218,126,125,218,91,91,91,92,90,90,218,126,106,181,75,75,77,77,75,76,181,105,106,181,76,76,75,76,75,75,181,4,76,98,101,71,93,14,5,67,59,186,174,80, +42,254,216,2,182,84,232,54,63,62,53,1,86,90,90,91,220,126,125,218,91,91,91,91,91,91,218,125,126,220,91,90,90,103,74,75,75,184,106,104,183,75,76,76,76,76,76,181,105,106,184,75,75,74,0,1,1,61,5,98,3,147,5,246,0,3,0,17,182,2,182,0,4,1,0,4,16,212,204,49, +0,16,212,236,48,1,33,21,33,1,61,2,86,253,170,5,246,148,0,2,1,43,3,117,3,166,5,240,0,14,0,26,0,32,64,17,21,204,9,205,15,204,0,150,27,24,83,6,84,18,83,12,27,16,212,236,252,236,49,0,16,244,236,252,236,48,1,50,22,23,30,1,21,20,6,35,34,38,53,52,54,23,34,6, +21,20,22,51,50,54,53,52,38,2,104,65,117,44,45,47,186,134,135,180,184,133,79,111,109,79,80,113,112,5,240,49,46,45,114,66,132,183,180,135,134,186,129,111,80,80,108,110,78,79,112,0,0,0,0,2,0,88,0,0,4,121,4,147,0,3,0,15,0,46,64,24,9,227,11,7,160,4,227,13, +5,0,160,2,6,1,26,8,4,28,12,0,26,14,10,16,16,212,60,236,50,252,60,236,50,49,0,47,236,212,60,236,252,60,236,48,55,33,21,33,1,17,33,21,33,17,35,17,33,53,33,17,88,4,33,251,223,2,100,1,189,254,67,168,254,68,1,188,170,170,4,147,254,183,170,254,180,1,76,170, +1,73,0,1,1,66,2,156,3,125,5,240,0,24,0,97,64,19,0,87,4,5,4,22,23,2,21,24,87,5,5,4,66,5,24,14,0,65,9,1,9,0,2,0,14,1,9,0,15,0,2,1,10,0,11,1,9,64,14,18,150,25,5,0,24,14,8,127,1,21,14,3,25,16,212,196,212,196,236,17,57,57,57,49,0,16,244,236,228,212,236,16, +238,17,57,57,48,75,83,88,7,16,4,237,17,23,57,7,16,5,237,89,34,1,33,21,33,53,55,62,1,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,7,1,227,1,154,253,197,231,101,81,100,82,49,113,63,65,121,59,142,172,74,119,3,14,114,110,226,97,122,51,61,76,36,36,125,28,28, +133,107,57,119,117,0,0,0,0,1,1,70,2,141,3,156,5,240,0,40,0,92,65,20,0,0,0,19,1,9,0,21,0,10,1,9,0,9,1,11,0,21,0,13,1,9,0,6,0,31,1,9,0,32,1,11,0,6,1,10,0,28,1,9,64,19,35,150,41,22,19,13,0,3,20,25,127,38,16,127,3,31,20,9,41,16,212,196,196,212,236,212,236, +17,23,57,57,49,0,16,244,236,228,244,236,16,238,198,246,238,16,238,57,48,1,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,2,219,94,99,190,177,58,114,59,69,113,45,101,118,110,109,66,74,93, +98,96,87,44,112,59,69,117,50,145,168,88,4,96,21,108,80,124,134,21,20,121,27,26,81,68,74,76,108,63,60,56,63,24,23,121,17,18,118,99,71,93,0,1,1,219,4,238,3,186,6,102,0,3,0,37,64,9,2,186,0,185,4,1,60,3,4,16,212,236,49,0,16,244,75,176,9,84,75,176,14,84,91, +88,185,0,0,0,64,56,89,236,48,1,51,1,35,2,244,198,254,187,154,6,102,254,136,0,0,0,0,1,0,195,254,84,4,158,4,96,0,32,0,76,64,42,19,25,31,3,22,6,3,9,12,3,1,18,6,140,15,139,28,22,153,0,195,10,1,194,33,25,11,9,32,31,2,0,18,9,6,11,74,2,6,0,70,33,16,244,236, +252,236,196,17,18,57,57,17,18,57,49,0,16,228,50,228,244,60,236,252,196,17,23,57,17,18,23,57,48,19,17,51,17,20,22,51,50,54,53,17,51,17,20,22,51,50,54,55,21,14,1,35,34,38,39,14,1,35,34,38,39,17,195,184,120,111,127,129,185,32,33,9,29,28,38,68,34,62,75,12, +46,133,89,92,127,44,254,84,6,12,253,72,142,151,170,166,2,141,252,160,59,56,10,13,148,23,22,79,79,80,78,76,80,253,213,0,1,0,106,255,59,4,6,5,213,0,13,0,35,64,17,4,8,0,136,6,2,14,0,7,87,5,3,87,1,49,11,14,16,220,252,252,212,236,57,49,0,16,196,50,244,196, +204,48,1,33,17,35,17,35,17,35,17,46,1,53,52,36,2,70,1,192,141,191,141,215,236,1,5,5,213,249,102,6,31,249,225,3,78,17,221,184,190,232,0,0,0,0,1,1,233,2,47,2,229,3,96,0,3,0,21,185,0,2,1,1,181,0,4,1,29,0,4,16,212,236,49,0,16,212,236,48,1,51,17,35,1,233, +252,252,3,96,254,207,0,255,255,1,139,254,117,3,41,0,0,16,6,2,175,0,0,0,1,1,88,2,156,3,147,5,223,0,10,0,57,65,11,0,7,0,0,1,9,0,9,0,3,1,9,0,4,0,9,1,10,0,2,1,9,64,13,5,150,11,8,97,6,87,3,125,0,97,1,11,16,212,236,236,252,236,49,0,16,244,236,228,212,236,16, +238,50,48,1,51,17,7,53,55,51,17,51,21,33,1,106,205,223,229,138,204,253,215,3,10,2,99,41,116,39,253,43,110,0,0,0,0,3,0,244,1,213,3,221,5,240,0,11,0,23,0,27,0,51,64,28,26,243,24,241,6,237,18,240,0,237,12,150,28,25,15,9,24,21,3,9,106,15,107,3,106,21,105, +28,16,252,236,252,236,17,18,57,17,18,57,49,0,16,244,236,244,236,252,236,48,1,34,6,21,20,22,51,50,54,53,52,38,39,50,22,21,20,6,35,34,38,53,52,54,3,33,21,33,2,104,102,115,115,102,101,117,115,103,170,203,202,171,170,202,203,171,2,164,253,92,5,123,156,139, +139,154,157,136,139,156,117,224,188,187,223,223,187,188,224,252,96,123,0,0,0,0,2,0,193,0,141,4,92,4,35,0,6,0,13,0,47,64,23,12,5,10,3,252,7,0,172,14,5,8,1,12,7,1,118,3,0,8,118,10,7,14,16,212,60,252,212,60,236,18,57,17,18,57,49,0,16,244,60,236,50,57,57, +48,9,1,21,1,53,9,1,37,1,21,1,53,9,1,2,135,1,213,254,43,1,45,254,211,254,58,1,213,254,43,1,45,254,211,4,35,254,94,82,254,94,191,1,12,1,12,191,254,94,82,254,94,191,1,12,1,12,255,255,0,27,254,242,4,90,6,123,16,39,7,72,0,184,252,86,16,39,0,123,254,254,0, +156,16,6,13,4,0,0,255,255,0,27,254,242,4,90,6,123,16,39,0,123,254,254,0,156,16,38,13,4,0,0,16,7,0,116,0,201,252,86,255,255,0,27,254,242,4,90,6,140,16,39,7,72,0,184,252,86,16,39,0,117,255,29,0,156,16,6,13,4,0,0,0,2,0,193,254,112,3,221,4,96,0,33,0,37,0, +130,64,71,11,10,9,8,7,5,12,6,37,25,26,25,3,4,2,2,5,37,26,26,25,66,33,26,5,2,4,6,25,0,16,139,15,141,12,0,34,134,36,12,151,19,195,36,194,38,6,35,25,22,9,31,5,0,3,29,1,26,35,9,41,22,15,29,3,1,15,34,30,35,38,16,212,252,196,212,236,16,214,238,17,57,17,18, +23,57,17,18,57,18,57,49,0,16,228,244,236,16,254,205,16,244,238,18,57,57,23,57,48,75,83,88,7,16,4,237,17,23,57,7,16,4,237,17,23,57,89,34,1,51,21,20,6,15,1,14,1,21,20,22,51,50,54,55,21,14,1,35,34,38,53,52,54,63,1,62,1,53,52,53,54,53,19,35,53,51,2,37,190, +61,84,90,62,47,131,109,78,178,98,94,191,104,186,221,67,94,88,67,38,2,196,202,202,2,207,154,98,137,82,89,59,88,49,89,110,69,68,188,57,56,192,161,76,131,92,86,64,84,63,1,4,23,19,1,14,254,255,255,0,37,0,0,4,172,7,107,16,38,0,36,0,0,17,7,13,1,0,0,1,117,0, +7,64,3,79,11,1,93,49,0,0,0,255,255,0,37,0,0,4,172,7,107,16,38,0,36,0,0,17,7,12,255,0,0,1,117,0,7,64,3,79,11,1,93,49,0,0,0,255,255,0,37,0,0,4,172,7,109,16,38,0,36,0,0,17,7,13,2,0,0,1,117,0,20,180,5,13,17,10,7,43,64,9,32,17,47,13,0,17,15,13,4,93,49,0,0, +255,255,0,37,0,0,4,172,7,94,16,38,0,36,0,0,17,7,13,0,0,0,1,117,0,16,180,5,35,20,10,7,43,64,5,79,35,64,20,2,93,49,0,0,255,255,0,37,0,0,4,172,7,78,16,38,0,36,0,0,17,7,12,254,0,0,1,117,0,28,180,5,17,14,10,7,43,64,17,112,14,127,17,48,14,63,17,32,14,47,17, +0,14,15,17,8,93,49,0,0,0,3,0,37,0,0,4,172,7,109,0,11,0,14,0,33,0,193,64,87,12,37,13,12,27,28,27,14,37,28,27,30,37,28,27,29,37,28,28,27,32,37,15,33,31,37,15,33,13,37,33,15,33,12,37,14,12,15,15,33,66,12,27,15,9,30,151,13,3,200,21,9,144,13,201,32,28,29, +28,24,32,33,31,13,18,6,30,14,24,12,6,27,0,80,24,15,6,80,18,24,75,28,47,18,75,33,34,16,220,228,252,228,16,238,50,16,238,50,17,57,17,57,57,17,18,57,57,17,57,17,18,57,49,0,47,60,230,230,214,238,16,238,18,57,57,57,48,75,83,88,7,16,8,237,7,16,5,237,7,5,237, +7,5,237,7,16,5,237,7,5,237,7,5,237,7,16,8,237,89,34,178,128,31,1,0,93,64,20,133,13,138,14,138,30,133,31,4,143,12,143,12,128,13,128,14,128,30,5,93,1,93,1,52,38,35,34,6,21,20,22,51,50,54,7,3,33,1,46,1,53,52,54,51,50,22,21,20,6,7,1,35,3,33,3,35,3,0,89,63, +64,87,88,63,63,89,152,213,1,170,254,148,58,65,160,114,114,161,64,59,1,172,209,110,253,245,108,209,6,90,63,89,87,65,63,88,88,252,253,8,3,80,33,121,73,114,161,161,114,73,118,36,250,137,1,133,254,123,0,0,2,0,0,0,0,4,156,5,213,0,15,0,19,0,103,64,55,13,37, +15,14,12,37,15,14,17,37,14,15,14,16,37,15,15,14,66,5,151,3,11,151,17,16,1,151,0,136,7,151,17,176,3,177,13,9,17,16,15,13,12,5,14,10,0,4,8,6,2,99,18,10,14,47,212,60,238,50,214,196,196,17,18,23,57,49,0,47,60,238,238,238,244,238,50,16,238,16,238,48,75,83, +88,7,16,5,237,7,16,5,237,7,5,237,7,5,237,89,34,1,21,33,17,33,21,33,17,33,21,33,17,33,3,35,1,23,3,33,17,4,137,254,174,1,51,254,205,1,101,253,225,254,160,101,184,1,154,120,202,1,53,5,213,170,254,70,170,253,227,170,1,127,254,129,5,213,170,252,252,3,4,0, +0,0,255,255,0,139,254,117,4,49,5,240,16,38,2,175,100,0,16,6,0,38,0,0,0,0,255,255,0,197,0,0,4,78,7,107,16,38,0,40,0,0,16,7,13,1,0,18,1,117,255,255,0,197,0,0,4,78,7,107,16,38,0,40,0,0,16,7,12,255,0,18,1,117,255,255,0,197,0,0,4,78,7,109,16,38,0,40,0,0,16, +7,13,2,0,18,1,117,255,255,0,197,0,0,4,78,7,78,16,38,0,40,0,0,16,7,12,254,0,18,1,117,255,255,0,201,0,0,4,6,7,107,16,38,0,44,0,0,16,7,13,1,0,0,1,117,255,255,0,201,0,0,4,6,7,107,16,38,0,44,0,0,16,7,12,255,0,0,1,117,255,255,0,201,0,0,4,6,7,109,16,38,0,44, +0,0,17,7,13,2,0,0,1,117,0,11,180,16,32,1,0,0,16,73,99,58,49,0,0,0,255,255,0,201,0,0,4,6,7,78,16,38,0,44,0,0,17,7,12,254,0,0,1,117,0,8,180,1,18,15,0,7,43,49,0,0,0,2,0,8,0,0,4,78,5,213,0,12,0,25,0,59,64,33,23,8,182,10,19,151,0,136,13,151,21,10,6,19,13, +6,0,4,22,20,16,50,3,49,9,48,24,20,30,11,7,48,26,16,252,60,236,50,236,252,236,16,196,23,57,49,0,47,198,50,238,246,238,16,238,50,48,1,32,0,17,16,0,41,1,17,35,53,51,17,1,32,54,17,16,38,33,35,17,33,21,33,17,1,180,1,86,1,68,254,187,254,171,254,209,125,125, +1,47,0,255,202,201,255,0,96,1,8,254,248,5,213,254,148,254,128,254,130,254,149,2,197,149,2,123,250,209,251,1,72,1,75,251,254,43,149,253,225,255,255,0,139,0,0,4,70,7,98,16,38,0,49,0,0,17,7,13,0,0,0,1,121,0,16,180,4,34,19,0,7,43,64,5,79,34,64,19,2,93,49, +0,0,255,255,0,117,255,227,4,92,7,107,16,38,0,50,0,0,17,7,13,1,0,0,1,117,0,7,64,3,79,24,1,93,49,0,0,0,255,255,0,117,255,227,4,92,7,107,16,38,0,50,0,0,17,7,12,255,0,0,1,117,0,7,64,3,79,24,1,93,49,0,0,0,255,255,0,117,255,227,4,92,7,109,16,38,0,50,0,0,17, +7,13,2,0,0,1,117,0,20,180,12,26,30,18,7,43,64,9,32,30,47,26,0,30,15,26,4,93,49,0,0,255,255,0,117,255,227,4,92,7,94,16,38,0,50,0,0,17,7,13,0,0,0,1,117,0,16,180,12,48,33,18,7,43,64,5,79,48,64,33,2,93,49,0,0,255,255,0,117,255,227,4,92,7,78,16,38,0,50,0, +0,17,7,12,254,0,0,1,117,0,28,180,12,30,27,18,7,43,64,17,112,27,127,30,48,27,63,30,32,27,47,30,0,27,15,30,8,93,49,0,0,0,1,0,150,0,174,4,59,4,84,0,11,0,46,64,28,10,8,7,6,4,2,1,0,8,11,9,5,3,12,11,10,9,8,7,5,4,3,1,9,6,2,0,12,16,212,60,204,23,57,49,0,16,212, +60,204,50,23,57,48,19,9,1,55,9,1,23,9,1,7,9,1,150,1,94,254,162,116,1,94,1,95,116,254,162,1,92,116,254,163,254,164,1,37,1,92,1,94,117,254,162,1,94,117,254,162,254,164,119,1,94,254,162,0,0,0,0,3,0,8,255,186,4,176,6,23,0,9,0,19,0,43,0,107,64,58,43,41,38, +11,10,9,0,4,14,29,31,32,20,14,3,42,38,30,3,151,26,14,151,38,150,26,153,31,31,30,44,32,35,17,42,20,23,11,10,9,0,4,6,29,35,17,41,6,43,6,50,23,54,17,50,35,53,44,16,252,236,252,236,192,18,57,17,18,57,18,23,57,17,57,57,17,18,57,17,57,57,49,0,47,228,244,236, +16,238,192,16,192,17,18,57,57,18,57,18,23,57,17,57,57,48,1,30,1,51,50,18,17,52,38,39,9,1,46,1,35,34,2,17,20,22,1,22,18,21,16,2,35,34,38,39,7,39,55,38,2,53,16,18,51,50,22,23,55,23,1,115,30,131,84,154,135,10,10,253,221,1,248,25,115,86,157,131,5,2,187,41, +43,247,253,121,180,61,143,103,178,32,37,247,252,115,173,57,139,100,1,47,78,90,1,25,1,73,110,136,45,253,203,2,207,81,85,254,220,254,134,80,101,2,230,81,254,254,163,254,122,254,128,81,81,203,70,252,73,1,6,158,1,135,1,128,82,80,201,74,0,255,255,0,147,255, +227,4,61,7,107,16,38,0,56,0,0,17,7,13,1,0,0,1,117,0,7,64,3,79,31,1,93,49,0,0,0,255,255,0,147,255,227,4,61,7,107,16,38,0,56,0,0,17,7,12,255,0,0,1,117,0,7,64,3,79,31,1,93,49,0,0,0,255,255,0,147,255,227,4,61,7,109,16,38,0,56,0,0,17,7,13,2,0,0,1,117,0,20, +180,17,32,36,1,7,43,64,9,32,36,47,32,0,36,15,32,4,93,49,0,0,255,255,0,147,255,227,4,61,7,78,16,38,0,56,0,0,17,7,12,254,0,0,1,117,0,28,180,17,36,33,1,7,43,64,17,112,33,127,36,48,33,63,36,32,33,47,36,0,33,15,36,8,93,49,0,0,255,255,0,37,0,0,4,172,7,107, +16,38,0,60,0,0,17,7,12,255,0,0,1,117,0,7,64,3,32,9,1,93,49,0,0,0,0,2,0,201,0,0,4,141,5,213,0,8,0,21,0,52,181,1,151,18,0,151,11,184,1,8,64,19,9,136,20,8,2,18,12,0,5,50,15,56,19,10,0,30,9,51,22,16,252,236,50,50,252,236,17,57,57,57,57,49,0,47,244,252,236, +212,236,48,1,17,51,50,54,53,52,38,35,1,51,17,51,32,22,21,20,6,33,35,17,35,1,147,234,158,157,157,158,254,76,202,254,1,4,248,248,254,252,254,202,4,33,253,243,132,131,131,131,1,180,254,242,210,218,219,209,254,145,0,0,1,0,188,255,227,4,125,6,20,0,47,0,86, +64,49,45,39,33,12,4,6,13,32,0,4,42,22,139,23,26,140,19,42,140,3,155,19,153,46,12,9,13,29,32,33,39,9,1,36,39,6,6,29,6,36,16,22,45,6,16,68,0,70,48,16,244,236,252,204,16,198,238,212,238,16,238,17,57,57,18,57,18,57,49,0,47,228,254,238,16,254,213,238,18,23, +57,23,57,48,19,52,54,51,50,22,23,14,1,21,20,22,31,1,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,47,1,46,1,53,52,54,55,46,1,35,34,6,21,17,35,188,210,216,204,210,2,155,168,55,67,58,151,111,224,196,69,135,66,76,133,59,108,128,65,120,67,92,91,162, +156,2,121,113,121,114,187,4,113,213,206,221,216,14,124,100,49,77,42,37,93,164,116,154,178,25,24,164,31,30,97,81,71,95,74,39,56,133,79,128,171,35,107,114,131,139,251,147,0,0,0,255,255,0,133,255,227,4,35,6,102,16,38,0,68,0,0,16,6,0,67,0,0,0,0,255,255,0, +133,255,227,4,35,6,102,16,38,0,68,0,0,16,6,0,118,0,0,0,0,255,255,0,133,255,227,4,35,6,102,16,38,0,68,0,0,16,6,2,103,0,0,0,0,255,255,0,133,255,227,4,35,6,55,16,38,0,68,0,0,16,6,2,121,0,0,0,0,255,255,0,133,255,227,4,35,6,16,16,38,0,68,0,0,16,6,0,106,0, +0,0,0,255,255,0,133,255,227,4,35,7,6,16,38,0,68,0,0,16,6,2,119,0,0,0,0,0,3,0,41,255,227,4,176,4,123,0,10,0,19,0,67,0,143,64,73,61,55,15,48,12,18,3,54,11,37,8,0,30,67,11,1,31,139,30,141,27,8,140,34,55,139,54,191,15,46,11,182,20,1,193,51,15,140,64,58,190, +40,34,153,68,2,5,0,24,37,61,3,47,18,46,5,21,18,77,47,0,117,30,11,77,20,67,5,77,54,43,115,68,16,244,196,236,252,236,196,252,196,236,50,18,57,17,18,23,57,17,18,57,49,0,16,228,50,244,60,236,50,244,60,236,50,16,244,238,16,254,60,244,238,17,18,57,18,57,17, +57,17,18,23,57,17,18,57,48,64,9,48,53,48,54,48,55,48,56,4,93,1,53,35,34,6,21,20,22,51,50,54,1,53,52,38,35,34,6,29,1,5,33,14,1,21,20,22,51,50,54,55,21,14,1,35,34,38,39,14,1,35,34,38,53,52,54,59,1,53,52,38,35,34,6,7,53,62,1,51,50,22,23,62,1,51,50,22,17, +2,31,49,169,120,89,83,92,74,1,237,77,87,87,76,1,235,254,21,1,1,101,112,79,129,50,55,132,71,110,149,32,39,133,97,156,163,200,191,117,99,94,56,132,62,77,132,60,91,124,37,33,132,89,174,145,1,186,72,90,113,89,97,133,1,143,52,151,133,136,157,43,143,15,35, +34,161,144,51,51,172,41,43,82,78,80,80,172,164,171,179,88,120,128,43,39,168,35,33,63,64,61,66,237,254,206,0,255,255,0,195,254,117,4,37,4,123,16,38,2,175,104,0,16,6,0,70,0,0,0,0,255,255,0,123,255,227,4,88,6,102,16,38,0,72,0,0,16,6,0,67,14,0,0,0,255,255, +0,123,255,227,4,88,6,102,16,38,0,72,0,0,16,6,0,118,14,0,0,0,255,255,0,123,255,227,4,88,6,102,16,38,0,72,0,0,16,6,2,103,14,0,0,0,255,255,0,123,255,227,4,88,6,16,16,38,0,72,0,0,17,6,0,106,14,0,0,7,64,3,64,29,1,93,49,0,255,255,0,178,0,0,4,68,6,102,16,38, +0,243,0,0,16,6,0,67,0,0,0,0,255,255,0,178,0,0,4,68,6,102,16,38,0,243,0,0,16,6,0,118,0,0,0,0,255,255,0,178,0,0,4,68,6,102,16,38,0,243,0,0,17,6,2,103,0,0,0,9,64,5,64,10,48,10,2,93,49,0,0,0,255,255,0,178,0,0,4,68,6,16,16,38,0,243,0,0,17,6,0,106,24,0,0,8, +180,3,16,13,6,7,43,49,0,2,0,137,255,227,4,72,6,20,0,26,0,41,0,139,64,79,18,23,19,18,1,0,13,14,15,16,4,17,23,0,1,0,22,23,23,24,23,21,23,20,21,24,24,23,66,26,25,24,21,20,19,6,22,15,30,18,0,22,30,140,12,36,140,6,153,12,22,155,42,18,21,24,3,39,20,19,22,3, +33,9,26,25,3,15,0,33,39,18,3,68,33,18,9,62,42,16,244,236,252,236,17,57,57,17,57,57,17,18,23,57,17,23,57,49,0,16,236,204,244,236,16,238,18,57,57,18,57,18,23,57,48,75,83,88,7,16,8,237,7,16,5,237,7,16,5,237,23,57,7,8,237,89,34,1,22,18,21,16,2,35,34,2,17, +16,18,51,50,22,23,46,1,39,5,39,55,39,51,23,37,23,3,46,1,35,34,6,21,20,22,51,50,54,53,52,38,2,205,197,182,251,229,228,251,251,224,34,35,15,33,72,38,254,233,30,237,182,219,127,1,33,33,174,35,82,45,146,153,148,136,137,148,58,5,47,212,254,132,200,254,244, +254,216,1,40,1,12,1,9,1,40,2,2,45,89,44,92,98,80,200,145,94,98,254,23,13,13,210,199,196,212,212,196,110,203,255,255,0,195,0,0,4,27,6,55,16,38,0,81,0,0,16,6,2,121,0,0,0,0,255,255,0,137,255,227,4,72,6,102,16,38,0,82,0,0,16,6,0,67,0,0,0,0,255,255,0,137, +255,227,4,72,6,102,16,38,0,82,0,0,16,6,0,118,0,0,0,0,255,255,0,137,255,227,4,72,6,102,16,38,0,82,0,0,17,6,2,103,0,0,0,16,180,15,26,30,21,7,43,64,5,15,26,0,30,2,93,49,255,255,0,137,255,227,4,72,6,55,16,38,0,82,0,0,17,6,2,121,0,0,0,24,180,15,46,32,21,7, +43,64,13,48,32,63,46,32,32,47,46,16,32,31,46,6,93,49,255,255,0,137,255,227,4,72,6,16,16,38,0,82,0,0,17,6,0,106,0,0,0,24,180,9,30,27,3,7,43,64,13,127,30,112,27,95,30,80,27,79,30,64,27,6,93,49,0,3,0,88,0,150,4,121,4,111,0,3,0,7,0,11,0,39,64,19,2,254,0, +4,254,6,8,160,0,10,12,9,5,1,119,8,4,0,12,16,212,60,196,252,60,196,49,0,16,212,196,252,212,236,16,238,48,1,51,21,35,17,51,21,35,5,33,21,33,1,238,245,245,245,245,254,106,4,33,251,223,1,139,245,3,217,246,162,170,0,0,0,0,3,0,47,255,160,4,150,4,188,0,9,0, +19,0,43,0,115,64,62,43,44,38,31,29,26,19,10,1,0,4,13,41,38,32,20,13,4,42,38,30,26,4,140,38,13,140,26,190,38,153,44,43,44,42,20,23,16,32,30,35,19,10,1,0,4,7,41,23,16,29,7,31,7,18,35,68,16,18,23,62,44,16,244,236,252,236,192,18,57,17,18,57,18,23,57,17,57, +57,17,18,57,57,17,57,49,0,16,228,244,236,16,238,16,192,16,192,17,18,57,57,18,57,18,23,57,17,57,57,17,18,57,48,9,1,30,1,51,50,54,53,52,38,39,46,1,35,34,6,21,20,22,23,7,46,1,53,16,18,51,50,22,23,55,23,7,30,1,21,16,2,35,34,38,39,7,39,3,109,254,49,36,101, +65,141,144,12,72,35,99,67,139,149,14,14,139,39,41,246,233,100,158,60,147,93,164,42,44,246,234,103,157,57,160,92,3,12,253,209,47,47,219,213,52,111,175,48,46,214,202,48,116,71,160,71,195,113,1,30,1,46,55,56,176,77,195,66,193,122,254,225,254,211,59,60,186, +76,0,0,0,255,255,0,195,255,227,4,27,6,102,16,38,0,88,0,0,16,6,0,67,0,0,0,0,255,255,0,195,255,227,4,27,6,102,16,38,0,88,0,0,16,6,0,118,0,0,0,0,255,255,0,195,255,227,4,27,6,102,16,38,0,88,0,0,17,6,2,103,0,0,0,16,180,11,22,26,1,7,43,64,5,15,22,0,26,2,93, +49,255,255,0,195,255,227,4,27,6,16,16,38,0,88,0,0,17,6,0,106,0,0,0,24,180,10,26,23,2,7,43,64,13,127,26,112,23,95,26,80,23,79,26,64,23,6,93,49,255,255,0,104,254,86,4,129,6,102,16,38,0,92,0,0,16,6,0,118,0,0,0,0,0,2,0,190,254,86,4,84,6,31,0,16,0,28,0,51, +64,28,5,0,26,20,140,8,26,140,14,153,8,190,1,195,3,197,29,17,18,11,71,23,4,0,6,2,70,29,16,244,236,50,50,252,236,49,0,16,236,228,228,244,236,16,238,17,57,57,48,37,17,35,17,51,17,62,1,51,50,18,17,16,2,35,34,38,1,52,38,35,34,6,21,20,22,51,50,54,1,119,185, +185,46,153,100,203,231,232,202,102,153,1,240,135,133,134,138,138,134,133,135,141,253,201,7,201,253,178,83,87,254,198,254,234,254,239,254,201,87,1,245,214,218,219,213,212,220,218,0,0,255,255,0,104,254,86,4,129,6,16,16,38,0,92,0,0,16,6,0,106,0,0,0,0,255, +255,0,37,0,0,4,172,7,48,16,38,13,11,0,0,17,6,0,36,0,0,0,20,180,9,2,3,14,7,43,64,9,64,3,79,2,32,3,47,2,4,93,49,255,255,0,133,255,227,4,35,5,246,16,38,2,140,0,0,16,6,0,68,0,0,0,0,255,255,0,37,0,0,4,172,7,109,16,38,13,6,0,0,17,6,0,36,0,0,0,24,180,19,8,0, +24,7,43,64,13,95,8,80,0,79,8,64,0,47,8,32,0,6,93,49,255,255,0,133,255,227,4,35,6,72,16,38,2,142,0,0,16,6,0,68,0,0,0,0,255,255,0,37,254,117,4,224,5,213,16,39,2,120,1,199,0,0,16,6,0,36,0,0,255,255,0,133,254,117,4,114,4,123,16,39,2,120,1,89,0,0,16,6,0,68, +0,0,255,255,0,139,255,227,4,49,7,107,16,38,0,38,0,0,16,7,12,255,0,90,1,117,255,255,0,195,255,227,4,37,6,102,16,38,0,70,0,0,16,6,0,118,90,0,0,0,255,255,0,139,255,227,4,49,7,116,16,39,13,2,0,126,1,124,16,6,0,38,0,0,255,255,0,195,255,227,4,37,6,102,16,38, +2,103,90,0,16,6,0,70,0,0,0,0,255,255,0,139,255,227,4,49,7,80,16,38,13,7,75,0,16,6,0,38,0,0,0,0,255,255,0,195,255,227,4,37,6,16,16,38,2,143,75,0,16,6,0,70,0,0,0,0,255,255,0,139,255,227,4,49,7,109,16,38,0,38,0,0,16,7,13,3,0,90,1,117,255,255,0,195,255,227, +4,37,6,102,16,38,0,70,0,0,16,6,2,104,90,0,0,0,255,255,0,137,0,0,4,82,7,103,16,38,0,39,0,0,16,7,13,3,255,178,1,111,255,255,0,123,255,227,5,32,6,21,16,39,12,253,2,58,255,175,17,6,0,71,0,0,0,13,185,0,0,0,64,56,64,3,127,0,1,93,49,0,255,255,0,8,0,0,4,78,5, +213,16,6,0,146,0,0,0,2,0,123,255,227,4,209,6,20,0,24,0,36,0,72,64,9,13,0,34,28,7,3,231,9,1,184,1,12,64,28,34,140,22,28,140,16,153,22,190,5,155,11,2,31,12,4,3,0,6,8,10,6,71,25,18,19,72,37,16,244,236,252,60,196,252,23,60,196,49,0,47,236,228,244,236,16, +238,253,60,238,50,17,18,57,57,48,1,17,33,53,33,53,51,21,51,21,35,17,35,53,14,1,35,34,2,17,16,18,51,50,22,1,20,22,51,50,54,53,52,38,35,34,6,3,90,254,207,1,49,184,191,191,184,46,153,100,203,233,234,202,101,154,254,15,136,133,133,139,139,133,133,136,3,209, +1,53,121,149,149,121,250,250,141,83,87,1,59,1,21,1,17,1,55,87,254,11,214,218,220,212,213,219,218,0,0,0,255,255,0,197,0,0,4,78,7,48,16,38,13,11,18,0,16,6,0,40,0,0,0,0,255,255,0,123,255,227,4,88,5,246,16,38,2,140,35,0,16,6,0,72,0,0,0,0,255,255,0,197,0, +0,4,78,7,109,16,38,13,6,18,0,16,6,0,40,0,0,0,0,255,255,0,123,255,227,4,88,6,72,16,38,2,142,14,0,16,6,0,72,0,0,0,0,255,255,0,197,0,0,4,78,7,80,16,38,13,7,18,0,16,6,0,40,0,0,0,0,255,255,0,123,255,227,4,88,6,16,16,38,2,143,14,0,16,6,0,72,0,0,0,0,255,255, +0,197,254,117,4,78,5,213,16,39,2,120,1,49,0,0,16,6,0,40,0,0,255,255,0,123,254,117,4,88,4,123,16,39,2,120,0,246,0,0,16,6,0,72,0,0,255,255,0,197,0,0,4,78,7,103,16,38,0,40,0,0,16,7,13,3,0,36,1,111,255,255,0,123,255,227,4,88,6,97,16,38,0,72,0,0,16,6,2,104, +35,251,0,0,255,255,0,102,255,227,4,80,7,109,16,39,13,2,0,0,1,117,16,6,0,42,0,0,255,255,0,123,254,72,4,18,6,102,16,38,2,103,0,0,16,6,0,74,0,0,0,0,255,255,0,102,255,227,4,80,7,109,16,38,13,6,50,0,16,6,0,42,0,0,0,0,255,255,0,123,254,72,4,18,6,72,16,38,2, +142,0,0,16,6,0,74,0,0,0,0,255,255,0,102,255,227,4,80,7,80,16,38,13,7,50,0,16,6,0,42,0,0,0,0,255,255,0,123,254,72,4,18,6,16,16,38,2,143,0,0,16,6,0,74,0,0,0,0,255,255,0,102,253,195,4,80,5,240,16,39,2,174,0,128,255,225,16,6,0,42,0,0,255,255,0,123,254,72, +4,18,6,78,16,39,2,154,0,17,1,46,16,6,0,74,0,0,255,255,0,137,0,0,4,72,7,109,16,39,13,2,0,0,1,117,17,6,0,43,0,0,0,20,180,12,2,6,7,7,43,64,9,32,6,47,2,0,6,15,2,4,93,49,0,0,255,255,0,195,0,0,4,27,7,109,16,39,13,2,0,0,1,117,17,6,0,75,0,0,0,24,0,75,176,18, +81,88,185,0,0,0,64,56,89,64,7,112,0,96,0,79,0,3,93,48,0,0,0,2,0,3,0,0,4,206,5,213,0,19,0,23,0,63,64,33,6,2,18,151,9,20,17,12,151,21,177,4,0,136,14,10,7,12,23,4,30,9,5,49,18,13,20,1,30,16,0,48,24,16,252,60,236,50,50,204,252,60,236,50,50,204,49,0,47,60, +228,50,252,236,220,60,60,236,50,50,48,19,51,21,33,53,51,21,51,21,35,17,35,17,33,17,35,17,35,53,51,23,21,33,53,137,202,2,42,202,135,135,202,253,214,202,134,134,202,2,42,5,213,224,224,224,164,251,175,2,199,253,57,4,81,164,164,224,224,0,0,0,0,1,0,70,0,0, +4,27,6,20,0,27,0,63,64,34,9,22,3,0,3,1,18,14,182,21,13,6,140,25,190,16,155,10,1,2,6,0,74,16,19,17,21,9,6,14,16,11,70,28,16,244,60,204,252,50,50,204,16,252,236,49,0,47,60,236,244,236,220,60,236,50,17,23,57,57,48,1,17,35,17,52,38,35,34,6,21,17,35,17,35, +53,51,53,51,21,33,21,33,17,62,1,51,50,22,4,27,185,106,113,129,139,184,125,125,184,1,97,254,159,49,168,115,171,169,2,182,253,74,2,182,151,142,183,171,253,135,4,246,164,122,122,164,254,194,96,99,225,255,255,0,201,0,0,4,6,7,94,16,39,13,0,0,0,1,117,17,6, +0,44,0,0,0,24,180,31,24,9,30,7,43,64,13,79,24,64,9,63,24,48,9,47,24,32,9,6,93,49,0,0,255,255,0,178,0,0,4,68,6,55,16,38,2,121,0,0,16,6,0,243,0,0,0,0,255,255,0,201,0,0,4,6,7,48,16,38,13,11,0,0,17,6,0,44,0,0,0,16,180,5,2,3,4,7,43,64,5,79,2,64,3,2,93,49, +255,255,0,178,0,0,4,68,5,246,16,38,2,140,0,0,16,6,0,243,0,0,0,0,255,255,0,201,0,0,4,6,7,109,16,38,13,6,0,0,17,6,0,44,0,0,0,16,180,15,8,0,14,7,43,64,5,79,8,64,0,2,93,49,255,255,0,178,0,0,4,68,6,72,16,38,2,142,0,0,16,6,0,243,0,0,0,0,255,255,0,201,254,117, +4,6,5,213,16,38,0,44,0,0,16,6,2,120,70,0,0,0,255,255,0,178,254,117,4,68,6,20,16,38,0,76,0,0,16,6,2,120,80,0,0,0,255,255,0,201,0,0,4,6,7,80,16,38,13,7,0,0,16,6,0,44,0,0,0,0,0,1,0,178,0,0,4,68,4,96,0,9,0,34,64,18,8,182,0,194,6,2,182,4,3,76,1,6,5,76,0,75, +7,10,16,212,228,236,252,236,49,0,47,236,50,244,236,48,1,33,17,33,21,33,53,33,17,33,1,0,1,215,1,109,252,110,1,109,254,225,4,96,252,47,143,143,3,66,0,0,0,2,255,255,255,230,4,204,5,216,0,20,0,32,0,61,64,31,1,0,178,4,151,17,153,33,10,24,32,151,11,21,136, +25,29,151,27,1,11,9,12,34,26,22,24,29,21,31,33,16,212,204,50,220,204,50,16,212,204,196,196,49,0,47,236,50,244,60,236,50,50,16,244,236,244,204,48,37,53,30,1,51,50,55,54,53,17,33,53,33,17,16,7,6,35,34,39,38,1,33,21,35,17,51,21,33,53,51,17,35,2,140,61,132, +71,97,39,38,254,253,1,141,72,72,168,65,65,64,253,45,2,93,228,228,253,163,228,228,64,236,81,81,74,75,203,3,68,170,252,18,254,230,117,117,22,22,5,195,170,251,127,170,170,4,129,0,0,0,0,4,255,251,254,75,4,138,6,20,0,13,0,17,0,27,0,31,0,73,64,38,10,140,9, +195,32,2,27,182,18,17,31,196,14,28,155,3,18,194,20,24,182,23,10,3,14,1,6,15,4,33,21,29,19,24,18,28,26,32,16,212,60,196,204,220,60,204,16,220,60,252,60,196,196,49,0,47,236,50,228,50,252,60,236,50,16,238,50,16,244,236,48,5,17,33,53,33,17,20,6,43,1,53,51, +50,54,17,51,21,35,5,33,17,33,21,33,53,33,17,35,19,51,21,35,3,210,254,195,1,245,179,165,254,234,90,90,184,184,252,105,1,130,1,44,253,18,1,43,235,235,151,151,31,3,229,143,251,140,195,211,156,125,6,165,233,192,252,47,143,143,3,66,2,67,233,255,255,0,109, +255,227,3,202,7,109,16,39,13,2,0,48,1,117,16,6,0,45,0,0,255,255,0,186,254,86,3,168,6,102,16,38,2,103,0,0,16,6,1,230,0,0,0,0,255,255,0,137,253,224,4,201,5,213,16,38,2,174,106,254,16,6,0,46,0,0,0,0,255,255,0,236,253,224,4,178,6,20,16,39,2,174,0,144,255, +254,16,6,0,78,0,0,0,1,0,236,0,0,4,178,4,96,0,11,0,196,64,57,8,23,9,8,5,6,5,7,23,6,6,5,9,23,3,2,8,23,7,8,3,2,5,23,6,5,2,3,2,4,23,3,3,2,66,8,5,2,3,3,0,194,10,6,8,5,4,3,6,9,1,6,6,68,0,69,12,16,244,236,236,50,17,23,57,49,0,47,60,236,50,23,57,48,75,83,88, +7,16,5,237,7,16,8,237,7,8,237,7,4,237,7,16,5,237,7,16,8,237,89,34,178,8,7,1,1,93,64,82,6,2,8,8,22,2,24,5,24,8,53,2,52,5,54,8,70,2,102,2,117,2,118,5,12,9,3,8,8,25,3,23,4,24,5,25,6,26,7,24,8,40,3,39,5,40,7,59,3,59,4,55,5,57,7,55,8,74,3,73,7,89,6,89,7,107, +3,105,4,105,6,105,7,121,3,120,5,121,6,121,7,28,93,0,93,19,51,17,1,51,9,1,35,1,7,17,35,236,190,1,227,224,254,71,1,254,225,254,98,137,190,4,96,254,47,1,209,254,90,253,70,2,66,129,254,63,0,255,255,0,200,0,0,4,115,7,108,16,39,12,255,254,237,1,118,17,6,0, +47,0,0,0,7,64,3,32,0,1,93,49,0,0,0,255,255,0,160,0,0,4,10,7,108,16,39,12,255,255,161,1,118,17,6,0,79,0,0,0,24,0,75,176,14,81,88,185,0,0,0,64,56,89,64,7,159,0,143,0,79,0,3,93,48,0,0,255,255,0,215,253,224,4,115,5,213,16,38,2,174,102,254,16,6,0,47,0,0,0, +0,255,255,0,160,253,224,4,10,6,31,16,38,2,174,251,254,16,6,0,79,0,0,0,0,255,255,0,215,0,0,4,115,5,213,16,39,12,253,0,174,255,109,16,6,0,47,0,0,255,255,0,160,0,0,4,134,6,31,16,39,12,253,1,160,255,185,16,6,0,79,0,0,255,255,0,215,0,0,4,115,5,213,16,39,0, +121,1,96,0,134,16,6,0,47,0,0,255,255,0,160,0,0,4,188,6,31,16,39,0,121,1,215,0,144,16,6,0,79,0,0,0,1,255,246,0,0,4,115,5,213,0,13,0,55,64,30,12,11,10,4,3,2,6,0,6,151,0,136,8,3,4,7,1,11,14,0,12,5,1,30,7,49,9,0,52,14,16,252,60,236,236,50,46,17,18,57,17, +18,57,57,49,0,47,228,236,17,23,57,48,19,51,17,37,23,1,17,33,21,33,17,7,39,55,215,203,1,59,78,254,119,2,209,252,100,145,80,225,5,213,253,152,219,111,254,238,253,227,170,2,59,106,110,158,0,0,0,0,1,0,76,0,0,4,10,6,31,0,21,0,62,64,33,20,19,18,12,11,10,6, +9,0,3,14,182,16,197,3,182,5,11,12,22,15,19,3,6,20,4,17,0,6,15,13,9,22,16,212,60,204,252,60,204,50,57,57,57,17,18,57,57,49,0,47,236,252,236,17,57,57,23,57,48,1,20,22,59,1,21,35,34,38,53,17,5,39,1,17,33,53,33,17,37,23,1,2,127,91,89,215,233,165,181,254, +213,80,1,123,254,217,1,223,1,59,80,254,117,1,150,124,126,156,212,194,1,36,209,111,1,8,2,47,144,253,190,219,110,254,237,0,0,255,255,0,139,0,0,4,70,7,107,16,39,12,255,0,33,1,117,16,6,0,49,0,0,255,255,0,195,0,0,4,27,6,109,16,38,0,118,20,7,16,6,0,81,0,0, +0,0,255,255,0,139,253,224,4,70,5,213,16,38,2,174,42,254,16,6,0,49,0,0,0,0,255,255,0,195,253,224,4,27,4,123,16,38,2,174,48,254,16,6,0,81,0,0,0,0,255,255,0,139,0,0,4,70,7,109,16,38,0,49,0,0,16,7,13,3,0,42,1,117,255,255,0,195,0,0,4,27,6,102,16,38,0,81,0, +0,16,6,2,104,244,0,0,0,255,255,0,24,0,0,4,150,6,20,16,38,0,81,123,0,16,7,2,97,254,73,0,0,0,1,0,147,254,86,4,61,5,242,0,29,0,50,64,28,24,19,13,0,4,21,16,151,27,150,22,136,21,7,151,6,21,7,13,30,0,49,19,23,30,22,48,30,16,244,236,50,252,236,196,49,0,47,212, +236,16,228,244,236,17,23,57,48,1,17,20,7,6,43,1,53,51,50,55,54,53,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,18,4,61,89,90,165,205,167,90,45,44,116,124,141,152,202,202,54,184,126,187,185,3,231,252,5,195,105,106,156,62,62,146,3,241,180,169,218,203, +252,87,5,213,198,111,116,254,251,0,0,0,0,1,0,195,254,86,4,27,4,123,0,32,0,50,64,28,25,20,13,0,4,22,16,140,29,190,23,194,22,6,182,7,22,7,13,6,0,74,20,24,6,23,70,33,16,244,236,50,252,236,196,49,0,47,212,236,16,228,244,236,17,23,57,48,1,17,20,7,6,43,1,53, +51,50,55,54,53,17,52,38,35,34,7,6,21,17,35,17,51,21,54,55,54,51,50,23,22,4,27,89,90,165,205,185,90,45,44,106,113,129,70,69,184,184,49,84,84,115,171,84,85,2,182,253,54,195,105,106,156,62,62,126,2,202,151,142,91,92,171,253,135,4,96,168,96,50,49,113,112, +0,0,0,255,255,0,117,255,227,4,92,7,48,16,38,13,11,0,0,17,6,0,50,0,0,0,20,180,16,2,3,22,7,43,64,9,79,2,64,3,47,2,32,3,4,93,49,255,255,0,137,255,227,4,72,5,246,16,38,2,140,0,0,17,6,0,82,0,0,0,8,180,19,2,3,25,7,43,49,255,255,0,117,255,227,4,92,7,109,16, +38,13,6,0,0,17,6,0,50,0,0,0,16,180,26,8,0,32,7,43,64,5,47,8,32,0,2,93,49,255,255,0,137,255,227,4,72,6,72,16,38,2,142,0,0,17,6,0,82,0,0,0,16,180,29,8,0,35,7,43,64,5,15,8,0,0,2,93,49,255,255,0,117,255,227,4,92,7,107,16,38,13,8,0,0,16,6,0,50,0,0,0,0,255, +255,0,137,255,227,4,72,6,102,16,38,2,147,0,0,16,6,0,82,0,0,0,0,0,2,0,72,0,0,4,193,5,213,0,16,0,25,0,59,64,31,14,151,12,17,10,151,8,136,23,0,151,12,177,1,23,17,8,2,20,15,11,30,24,9,13,0,45,20,30,5,26,16,220,236,252,196,196,212,236,50,18,57,57,57,57,49, +0,47,236,236,50,244,236,50,16,238,48,37,21,33,32,2,17,16,18,41,1,21,33,17,33,21,33,17,1,34,6,17,16,22,59,1,17,4,193,253,163,254,217,245,244,1,40,2,82,254,154,1,72,254,184,254,254,177,139,139,177,61,170,170,1,77,1,156,1,161,1,75,170,254,70,170,253,227, +4,129,230,254,164,254,166,229,4,129,0,3,0,14,255,227,4,186,4,123,0,10,0,22,0,56,0,105,64,57,50,47,9,6,0,25,31,23,38,32,11,56,23,0,32,139,31,141,11,0,182,23,28,11,140,35,23,193,17,6,140,53,47,190,41,35,153,57,0,3,50,38,24,9,77,14,117,31,3,77,23,67,20, +77,44,115,57,16,244,236,252,236,196,252,236,50,57,57,17,57,49,0,16,228,50,244,60,236,50,228,16,238,50,16,238,16,244,238,17,18,57,17,18,57,17,18,57,17,18,57,17,57,48,1,52,54,53,52,38,35,34,6,29,1,1,50,54,53,16,38,35,34,6,17,16,22,1,33,21,20,22,51,50,54, +55,21,14,1,35,34,38,39,14,1,35,34,2,17,16,18,51,50,22,23,62,1,51,50,22,17,4,23,2,80,86,87,77,254,166,102,82,80,104,103,80,80,3,172,254,21,99,112,80,131,47,59,125,74,98,147,48,52,128,84,189,170,170,189,89,128,47,37,130,87,175,144,2,145,11,38,9,145,135, +137,158,43,253,234,168,239,1,35,174,167,254,243,254,243,167,1,135,84,163,144,53,51,172,43,41,67,66,68,65,1,20,1,56,1,56,1,20,62,65,62,65,237,254,206,0,0,255,255,0,143,0,0,4,209,7,107,16,39,12,255,255,181,1,117,16,6,0,53,0,0,255,255,1,106,0,0,4,136,6, +109,16,39,0,118,0,206,0,7,16,6,0,85,0,0,255,255,0,143,253,224,4,209,5,213,16,38,2,174,114,254,16,6,0,53,0,0,0,0,255,255,1,32,253,224,4,131,4,123,16,38,2,174,136,254,16,6,0,85,0,0,0,0,255,255,0,143,0,0,4,209,7,103,16,38,0,53,0,0,16,7,13,3,255,196,1,111, +255,255,1,106,0,0,4,131,6,102,16,38,0,85,0,0,16,6,2,104,90,0,0,0,255,255,0,139,255,227,4,74,7,107,16,39,12,255,0,25,1,117,16,6,0,54,0,0,255,255,0,213,255,227,4,6,6,109,16,38,0,118,26,7,16,6,0,86,0,0,0,0,255,255,0,139,255,227,4,74,7,109,16,39,13,2,0,0, +1,117,16,6,0,54,0,0,255,255,0,213,255,227,4,6,6,102,16,38,2,103,0,0,16,6,0,86,0,0,0,0,255,255,0,139,254,117,4,74,5,240,16,38,2,175,0,0,16,6,0,54,0,0,0,0,255,255,0,213,254,117,4,6,4,123,16,38,2,175,0,0,16,6,0,86,0,0,0,0,255,255,0,139,255,227,4,74,7,109, +16,38,0,54,0,0,16,7,13,3,0,0,1,117,255,255,0,213,255,227,4,6,6,102,16,38,0,86,0,0,16,6,2,104,0,0,0,0,255,255,0,47,254,117,4,162,5,213,16,38,2,175,0,0,16,6,0,55,0,0,0,0,255,255,0,131,254,117,4,8,5,158,16,38,2,175,121,0,16,6,0,87,0,0,0,0,255,255,0,47,0, +0,4,162,7,109,16,38,0,55,0,0,17,7,13,3,0,6,1,117,0,8,180,1,13,9,0,7,43,49,0,0,255,255,0,131,0,0,4,8,6,126,16,38,0,87,0,0,16,7,12,253,1,20,0,24,0,1,0,47,0,0,4,162,5,213,0,15,0,45,64,23,4,12,151,7,11,3,15,151,0,136,8,1,58,5,7,3,30,12,0,58,10,14,16,16,212, +60,236,204,252,60,204,236,49,0,47,244,236,50,212,60,236,50,48,19,33,21,33,17,33,21,33,17,35,17,33,53,33,17,33,47,4,115,254,45,1,9,254,247,203,254,247,1,9,254,43,5,213,170,253,192,170,253,191,2,65,170,2,64,0,1,0,131,0,0,4,8,5,158,0,27,0,66,64,33,18,9, +12,5,21,182,8,20,4,24,182,27,1,25,194,12,182,15,12,15,13,2,6,8,4,0,6,21,25,19,23,27,28,16,212,60,60,196,196,252,60,60,196,196,50,57,57,49,0,47,236,244,60,196,236,50,212,60,236,50,17,57,57,48,1,17,33,21,33,21,51,21,35,21,20,22,59,1,21,35,34,38,61,1,35, +53,51,53,33,53,33,17,2,102,1,162,254,94,229,229,94,117,207,225,207,170,229,229,254,213,1,43,5,158,254,194,143,233,142,233,124,98,147,166,203,233,142,233,143,1,62,0,255,255,0,147,255,227,4,61,7,94,16,39,13,0,0,0,1,117,17,6,0,56,0,0,0,16,180,47,24,9,31, +7,43,64,5,79,24,64,9,2,93,49,0,0,255,255,0,195,255,227,4,27,6,55,16,38,2,121,0,0,17,6,0,88,0,0,0,16,180,39,22,8,29,7,43,64,5,47,22,32,8,2,93,49,255,255,0,147,255,227,4,61,7,48,16,38,13,11,0,0,17,6,0,56,0,0,0,20,180,21,2,3,5,7,43,64,9,79,2,64,3,47,2,32, +3,4,93,49,255,255,0,195,255,227,4,27,5,246,16,38,2,140,0,0,17,6,0,88,0,0,0,8,180,15,1,0,5,7,43,49,255,255,0,147,255,227,4,61,7,109,16,38,13,6,0,0,17,6,0,56,0,0,0,16,180,31,8,0,15,7,43,64,5,47,8,32,0,2,93,49,255,255,0,195,255,227,4,27,6,72,16,38,2,142, +0,0,17,6,0,88,0,0,0,16,180,25,8,0,15,7,43,64,5,15,8,0,0,2,93,49,255,255,0,147,255,227,4,61,7,109,16,38,0,56,0,0,16,6,2,119,10,103,0,0,255,255,0,195,255,227,4,27,6,217,16,38,0,88,0,0,16,6,2,119,15,211,0,0,255,255,0,147,255,227,4,61,7,107,16,38,13,8,0, +0,16,6,0,56,0,0,0,0,255,255,0,195,255,227,4,27,6,102,16,38,2,147,0,0,16,6,0,88,0,0,0,0,255,255,0,147,254,101,4,61,5,213,16,38,0,56,0,0,16,6,2,120,28,240,0,0,255,255,0,195,254,117,4,176,4,94,16,38,0,88,0,0,16,7,2,120,1,151,0,0,255,255,0,0,0,0,4,209,7, +116,16,39,13,2,0,0,1,124,17,6,0,58,0,0,0,8,180,14,2,6,7,7,43,49,0,0,255,255,0,0,0,0,4,209,6,109,16,38,2,103,0,7,17,6,0,90,0,0,0,8,180,14,2,6,7,7,43,49,255,255,0,37,0,0,4,172,7,116,16,39,13,2,0,0,1,124,17,6,0,60,0,0,0,8,180,11,2,6,7,7,43,49,0,0,255,255, +0,104,254,86,4,129,6,109,16,38,2,103,12,7,16,6,0,92,0,0,0,0,255,255,0,37,0,0,4,172,7,78,16,38,0,60,0,0,17,7,12,254,0,0,1,117,0,8,180,4,15,12,0,7,43,49,0,0,255,255,0,156,0,0,4,145,7,107,16,39,12,255,0,27,1,117,16,6,0,61,0,0,255,255,0,203,0,0,4,16,6,109, +16,38,0,118,86,7,16,6,0,93,0,0,0,0,255,255,0,156,0,0,4,145,7,80,16,38,13,7,50,0,16,6,0,61,0,0,0,0,255,255,0,203,0,0,4,16,6,16,16,38,2,143,0,0,16,6,0,93,0,0,0,0,255,255,0,156,0,0,4,145,7,109,16,38,0,61,0,0,16,7,13,3,0,0,1,117,255,255,0,203,0,0,4,16,6, +102,16,38,0,93,0,0,16,6,2,104,0,0,0,0,0,1,0,195,0,0,4,39,6,20,0,15,0,44,64,22,0,7,12,4,182,5,12,140,11,155,5,194,2,13,10,11,0,6,5,3,7,16,16,212,60,196,252,196,57,57,49,0,47,228,252,236,16,238,18,57,57,48,1,17,35,17,33,53,33,53,52,54,59,1,21,35,34,6,2, +166,184,254,213,1,43,169,179,221,209,99,77,4,195,251,61,3,209,143,78,184,174,153,81,0,0,2,0,70,255,227,4,88,6,20,0,26,0,37,0,0,1,62,1,51,50,18,17,16,2,35,34,38,39,21,35,17,35,53,51,53,51,21,51,33,21,33,35,0,16,38,35,34,6,21,20,22,51,50,1,121,44,155,102, +202,232,233,203,100,153,46,184,123,123,184,2,1,97,254,159,2,2,29,136,133,134,138,138,134,133,3,209,82,88,254,201,254,239,254,235,254,197,87,83,141,4,246,164,122,122,164,252,99,1,172,218,219,213,212,220,0,0,3,0,20,0,0,4,165,5,213,0,8,0,17,0,41,0,63,64, +36,25,0,151,10,9,151,18,136,1,151,10,177,31,17,11,25,31,19,8,2,7,0,14,30,22,5,50,28,9,0,30,18,33,36,39,43,16,212,220,212,57,236,50,220,236,212,236,17,23,57,49,0,47,236,236,244,236,16,238,57,48,1,17,51,50,54,53,52,38,35,3,17,51,50,54,53,52,38,35,37,33, +50,22,21,20,6,7,30,1,21,20,4,41,1,17,34,6,29,1,35,53,52,54,2,28,120,176,150,158,168,120,116,146,131,129,148,254,194,1,66,229,248,131,131,147,167,254,246,254,249,254,190,62,100,156,169,2,201,253,221,123,141,146,137,2,102,254,62,112,125,113,100,166,198, +181,137,158,20,22,207,160,203,207,5,47,87,112,49,70,159,185,0,255,255,0,166,0,0,4,113,5,213,16,6,3,80,0,0,0,2,0,193,255,227,4,88,6,20,0,18,0,29,0,0,1,62,1,51,50,18,17,16,2,35,34,38,39,21,35,17,33,21,33,0,16,38,35,34,6,21,20,22,51,50,1,121,44,155,102, +202,232,233,203,100,153,46,184,2,240,253,200,2,29,136,133,134,138,138,134,133,3,209,82,88,254,201,254,239,254,235,254,197,87,83,141,6,20,184,251,253,1,172,218,219,213,212,220,0,0,2,0,48,0,0,4,161,5,213,0,10,0,24,0,0,1,17,51,50,55,54,53,52,39,38,35,39, +51,4,23,22,21,20,7,6,41,1,17,39,1,1,161,239,176,75,75,79,79,168,239,235,1,123,101,53,133,133,254,249,254,70,166,1,113,2,201,253,221,62,61,141,146,68,69,164,15,191,100,161,203,103,104,3,180,228,1,61,0,2,0,60,255,227,4,148,6,20,0,12,0,33,0,0,0,16,38,35, +34,7,6,21,20,23,22,51,50,1,62,1,51,50,23,22,17,16,7,6,35,34,39,38,39,21,35,17,39,1,3,210,136,132,134,70,68,68,70,134,132,254,108,44,154,102,202,116,116,116,116,204,100,76,76,46,184,194,1,122,1,89,1,172,218,109,110,213,212,110,110,3,82,82,88,155,156,254, +239,254,235,158,157,43,44,83,141,3,180,228,1,124,0,1,0,139,255,227,4,49,5,240,0,25,0,47,64,7,19,50,6,49,0,12,26,16,220,60,244,236,49,0,64,18,13,179,12,178,16,151,9,25,179,0,178,22,151,3,150,9,153,26,16,228,244,236,244,236,16,238,246,238,48,19,62,1,51, +32,0,17,16,0,33,34,38,39,53,30,1,51,50,18,17,16,2,35,34,6,7,139,77,162,91,1,29,1,63,254,195,254,225,91,162,77,73,169,88,197,196,196,197,86,170,74,5,158,41,41,254,103,254,146,254,144,254,106,41,41,207,61,64,1,48,1,50,1,51,1,48,64,61,0,0,1,0,60,255,227, +4,149,6,103,0,34,0,0,37,14,1,35,32,0,17,16,0,33,50,23,54,55,54,59,1,21,34,7,6,29,1,46,1,35,34,2,21,16,18,51,50,54,55,3,226,77,162,91,254,225,254,195,1,63,1,29,90,79,23,42,90,165,20,84,51,44,74,170,86,197,196,196,197,88,169,73,53,41,41,1,150,1,112,1,42, +1,153,20,51,50,106,156,62,53,135,70,61,64,254,208,239,254,206,254,208,64,61,0,0,0,0,1,0,94,255,227,4,115,5,142,0,33,0,0,37,14,1,35,32,0,16,0,33,50,23,54,55,54,59,1,21,34,7,6,29,1,46,1,35,34,6,21,20,22,51,50,54,55,3,192,74,157,82,254,252,254,219,1,37, +1,4,70,67,19,61,90,165,20,90,45,44,73,147,93,173,186,187,172,96,152,65,57,43,43,1,56,2,40,1,56,16,114,71,106,156,62,62,126,148,65,58,224,208,207,225,59,62,0,255,255,0,8,0,0,4,78,5,213,16,6,0,146,0,0,0,2,0,8,0,0,4,201,5,213,0,18,0,27,0,0,1,51,32,0,17, +16,0,33,35,17,34,7,6,29,1,35,53,52,54,1,32,54,17,16,38,33,35,17,1,70,233,1,86,1,68,254,188,254,170,233,54,60,48,156,192,1,99,0,255,202,201,255,0,26,5,213,254,148,254,128,254,130,254,149,5,47,47,38,114,49,70,181,163,250,209,251,1,72,1,75,251,251,119,0, +0,2,0,131,0,0,4,78,5,213,0,8,0,22,0,0,1,35,34,6,21,20,22,59,1,1,53,33,17,33,32,36,53,52,55,54,37,51,17,3,131,239,168,158,150,176,239,253,69,3,134,254,70,254,249,254,246,53,101,1,123,235,2,201,137,146,141,123,4,137,166,250,43,207,203,161,100,191,15,1, +194,0,0,0,0,2,0,157,255,227,4,52,6,20,0,10,0,29,0,0,0,16,22,51,50,54,53,52,38,35,34,3,53,33,17,35,53,14,1,35,34,2,17,16,18,51,50,22,23,17,1,95,136,133,134,138,138,134,133,163,2,240,184,46,153,100,203,233,232,202,102,155,44,3,5,254,84,218,220,212,213, +219,1,125,184,249,236,141,83,87,1,59,1,21,1,17,1,55,88,82,1,139,0,0,0,2,0,136,254,61,4,71,4,123,0,11,0,55,0,0,37,50,54,53,52,38,35,34,6,21,20,22,5,22,23,22,21,20,7,6,35,34,47,1,53,22,23,22,51,50,51,55,54,63,1,54,53,52,39,38,39,38,39,38,39,38,17,16,18, +51,50,18,17,16,7,6,2,104,140,144,144,140,141,144,144,1,167,19,40,62,118,119,197,102,50,151,66,70,75,73,9,10,32,73,60,39,27,13,17,41,24,105,235,121,124,246,234,233,246,123,31,127,218,214,213,219,219,213,214,218,76,9,40,61,92,136,82,82,12,36,173,24,15, +15,1,2,43,28,24,46,33,19,24,21,13,1,3,148,151,1,30,1,31,1,45,254,211,254,225,254,226,151,38,0,0,0,0,1,0,197,0,0,4,78,5,213,0,11,0,43,64,10,8,4,30,0,49,11,6,3,51,12,16,252,196,196,252,236,50,49,0,64,12,6,151,8,10,151,0,136,4,151,8,177,2,47,236,236,244, +236,16,238,48,1,17,33,53,33,17,33,53,33,17,33,53,4,78,252,119,2,191,253,114,2,142,253,84,5,213,250,43,170,2,29,170,1,186,170,0,2,0,117,255,227,4,92,5,240,0,21,0,28,0,61,64,12,3,2,28,50,16,54,9,22,50,0,53,29,16,244,236,196,244,236,57,57,49,0,64,20,0,22, +3,1,10,179,9,6,151,13,150,29,22,151,1,25,151,19,153,29,16,244,236,212,238,16,244,244,212,238,18,57,17,57,48,19,53,33,53,52,2,35,34,6,7,53,62,1,51,50,18,17,16,2,35,34,2,19,20,18,51,50,18,55,117,3,19,138,150,86,170,74,77,162,91,253,247,247,253,253,246, +215,140,148,148,126,9,2,233,83,8,241,1,23,64,61,207,41,41,254,128,254,121,254,122,254,128,1,126,1,35,248,254,251,0,255,254,0,0,1,0,137,255,227,4,55,5,240,0,40,0,62,64,11,20,9,31,16,50,3,25,50,38,48,41,16,252,236,212,236,212,196,196,49,0,64,22,10,179, +9,13,151,6,150,41,0,22,151,19,177,41,31,179,32,28,151,35,153,41,16,244,236,212,236,16,244,236,57,16,244,236,212,236,48,1,46,1,53,52,36,51,50,22,23,21,46,1,35,34,6,21,20,22,59,1,21,35,34,6,21,20,22,51,50,54,55,21,14,1,35,34,36,53,52,54,1,184,131,137,1, +5,218,73,189,121,104,190,89,134,145,156,139,154,154,152,178,178,166,98,198,102,103,214,103,245,254,235,156,3,31,34,162,123,181,221,32,32,186,40,40,123,115,109,122,166,153,130,141,150,52,53,201,36,38,235,206,149,199,0,1,0,63,254,86,4,146,5,213,0,19,0, +0,1,33,21,33,17,33,21,33,17,20,7,6,43,1,53,51,50,55,54,53,1,124,3,22,253,181,2,12,253,244,89,90,165,176,138,90,45,44,5,213,170,254,72,170,253,35,195,105,106,156,62,62,126,0,0,1,0,195,254,86,4,39,6,20,0,36,0,0,1,21,43,1,34,7,6,29,1,33,21,33,17,20,7,6, +43,1,53,51,50,55,54,53,3,33,53,33,53,52,55,54,55,54,59,2,4,39,209,2,97,39,38,1,129,254,127,81,82,181,70,49,105,38,38,2,254,215,1,40,87,37,60,70,97,9,3,6,20,153,41,40,103,99,143,252,27,214,96,96,156,48,49,153,3,229,143,78,180,92,39,21,26,0,0,1,0,52,255, +227,4,157,6,103,0,40,0,0,37,14,1,35,32,0,17,16,0,33,50,23,22,23,54,55,54,59,1,21,34,7,6,7,21,46,1,35,34,2,17,16,18,51,50,54,55,17,35,53,33,4,30,82,202,118,254,228,254,196,1,64,1,28,94,86,17,17,15,21,90,166,19,84,51,43,1,80,170,96,196,198,192,198,66,102, +40,216,1,154,123,75,77,1,151,1,111,1,110,1,153,26,6,6,26,25,106,156,62,54,134,27,77,73,254,207,254,206,254,201,254,213,31,33,1,145,166,0,0,2,0,28,254,82,4,182,5,73,0,13,0,21,0,0,1,0,17,20,33,32,53,16,9,1,51,9,1,51,1,2,17,20,51,50,53,16,2,218,1,68,254, +96,254,72,1,38,254,48,216,1,116,1,116,218,253,162,198,216,204,2,138,254,63,254,117,236,236,1,111,1,228,2,184,253,213,2,43,252,166,254,211,254,188,138,138,1,69,0,0,0,0,1,0,65,0,0,4,144,6,20,0,38,0,0,1,17,35,20,23,22,55,54,55,54,53,17,51,17,20,6,35,34, +39,38,53,17,52,38,35,34,6,21,17,35,17,51,17,54,55,54,51,50,22,2,243,1,34,38,55,19,54,47,167,152,154,127,74,73,95,66,71,125,166,166,77,17,75,85,118,152,2,182,254,224,153,49,52,4,2,73,66,156,1,155,254,101,228,225,96,96,214,1,32,151,142,183,171,253,135, +6,20,253,164,134,12,49,225,0,0,0,0,1,0,201,0,0,4,58,5,213,0,17,0,0,1,33,53,33,21,33,17,20,23,22,59,1,23,35,34,39,38,53,2,2,254,199,3,61,254,199,44,45,90,185,1,217,170,92,89,5,43,170,170,252,122,127,61,62,171,106,102,198,0,0,0,1,0,201,0,0,4,6,5,213,0, +21,0,0,19,33,21,33,17,51,33,21,33,35,17,33,21,33,53,33,17,33,53,33,17,33,201,3,61,254,199,2,1,9,254,247,2,1,57,252,195,1,57,254,249,1,7,254,199,5,213,170,253,192,170,254,105,170,170,1,151,170,2,64,0,0,0,1,0,110,0,0,4,195,5,213,0,25,0,0,1,54,55,54,51, +50,31,1,7,39,38,35,34,7,6,15,1,1,35,1,7,17,35,17,51,17,2,135,161,105,21,20,126,92,47,106,33,45,60,17,19,66,109,164,2,86,244,254,25,154,203,203,4,156,170,12,3,99,51,114,37,51,4,15,115,172,252,141,2,236,164,253,184,5,213,253,104,0,0,1,0,236,0,0,4,178,6, +20,0,23,0,0,19,53,52,55,54,59,1,21,35,34,7,6,21,51,17,1,51,9,1,35,1,7,17,35,236,89,90,165,205,185,90,45,44,5,1,227,224,254,71,1,254,225,254,98,137,190,3,234,148,195,105,106,156,62,62,126,254,17,1,209,254,90,253,70,2,66,129,254,63,0,0,1,0,160,0,0,4,10, +6,31,0,23,0,0,1,20,22,59,1,21,35,34,38,61,1,35,53,51,17,33,53,33,17,59,1,21,43,1,2,127,91,89,215,233,165,181,228,228,254,217,1,223,9,221,221,9,1,150,124,126,156,212,194,196,142,2,167,144,252,201,142,0,0,1,0,49,0,0,4,109,5,213,0,15,0,0,1,37,23,9,1,35, +9,1,35,1,39,5,39,1,3,51,2,67,1,92,80,254,141,1,241,191,254,191,254,182,191,1,169,34,254,150,80,1,129,174,191,4,189,242,110,254,254,251,193,2,192,253,64,3,145,74,251,111,1,10,1,124,0,1,0,109,255,229,4,111,5,213,0,34,0,0,37,14,1,35,34,38,25,1,51,17,20, +22,51,50,54,53,17,51,17,20,22,51,50,54,53,17,51,17,35,53,14,1,35,34,38,2,56,34,105,74,135,111,168,53,70,80,59,168,57,74,73,57,167,167,33,99,63,76,101,114,72,69,209,1,33,3,254,252,10,237,115,123,229,3,246,252,10,240,112,123,229,3,246,250,43,96,60,63,70, +0,0,1,0,29,254,86,4,25,5,213,0,18,0,0,19,51,1,17,51,17,35,1,17,20,7,6,43,1,53,50,55,54,53,190,230,1,198,175,230,254,59,81,81,148,27,81,40,40,5,213,251,51,4,205,250,43,4,205,251,31,195,105,106,156,62,61,127,0,0,1,0,195,254,82,4,27,4,123,0,19,0,0,1,17, +35,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,22,4,27,185,106,113,129,139,184,184,49,168,115,171,169,2,182,251,156,4,100,151,142,183,171,253,135,4,96,168,96,99,225,0,0,0,3,0,117,255,227,4,92,5,240,0,10,0,19,0,28,0,0,1,16,2,32,2,17,16,18,51,50,18,3, +2,39,38,35,34,7,6,3,23,22,23,22,51,50,55,54,55,4,92,247,254,6,246,247,252,253,247,212,8,58,68,154,153,67,59,8,1,9,57,67,153,154,68,56,9,2,233,254,122,254,128,1,126,1,136,1,135,1,128,254,128,254,204,1,8,123,141,141,123,254,248,184,250,118,141,141,117, +251,255,255,0,6,255,227,4,167,6,21,16,39,2,163,1,121,1,164,16,6,0,50,145,0,255,255,0,32,255,227,4,178,4,123,16,39,2,163,1,132,0,0,16,6,0,82,151,0,0,2,0,45,255,227,4,164,5,240,0,16,0,27,0,0,19,16,37,54,51,50,23,55,51,17,35,17,7,17,6,32,2,1,38,35,34,2, +17,16,18,51,50,55,45,1,78,53,62,206,111,147,230,175,180,111,254,56,221,2,136,61,138,138,121,121,138,138,61,2,233,2,160,89,14,158,131,250,43,4,205,160,252,118,192,1,126,3,94,141,254,230,254,183,254,184,254,230,141,0,0,2,0,86,254,82,4,171,4,123,0,19,0, +32,0,0,19,16,55,54,51,50,23,21,55,51,17,35,17,7,17,6,35,34,39,38,55,16,23,22,51,50,55,17,38,35,34,3,6,86,250,80,101,210,111,126,231,176,181,110,211,234,111,86,176,215,19,21,127,65,65,127,206,40,9,2,47,1,180,115,37,151,43,110,250,43,4,205,157,253,248, +151,188,146,254,254,117,34,3,109,2,134,109,254,226,66,0,0,0,2,0,56,0,0,4,153,5,213,0,23,0,33,0,0,1,16,5,6,43,1,17,35,17,34,7,6,29,1,35,53,52,55,54,51,33,32,19,22,1,50,55,54,53,52,38,43,1,17,4,153,254,200,86,110,93,202,54,60,48,156,96,96,126,1,39,1,151, +82,19,254,4,211,64,22,156,141,93,4,23,254,164,77,22,253,168,5,47,47,38,114,49,70,181,82,81,254,220,69,254,146,157,56,68,133,147,253,207,0,0,0,0,2,0,190,254,86,4,84,5,152,0,14,0,42,0,0,1,16,23,22,51,50,54,53,16,39,34,35,34,3,6,17,54,55,50,51,50,18,17, +16,2,35,34,38,39,17,35,17,16,55,54,59,1,21,35,34,7,6,21,1,119,209,29,34,133,135,251,9,8,214,46,12,91,194,7,7,203,231,232,202,102,153,44,185,203,63,78,205,185,169,9,1,2,47,254,137,50,7,218,214,1,162,14,254,239,70,1,73,164,6,254,198,254,234,254,239,254, +201,87,83,253,201,5,172,1,46,79,25,156,221,14,15,0,2,0,143,254,248,4,209,5,213,0,22,0,31,0,0,1,22,23,22,23,19,35,3,46,1,43,1,17,35,17,51,17,51,50,4,21,20,6,1,17,51,50,54,53,52,38,35,2,248,78,55,54,83,203,217,178,77,123,99,193,203,203,213,246,1,6,161, +253,208,221,145,142,151,144,1,185,20,55,55,167,254,104,1,121,161,93,254,145,5,213,254,248,222,210,148,187,2,89,253,238,130,134,129,137,0,0,0,0,1,0,139,255,227,4,74,5,240,0,39,0,0,19,62,1,51,50,4,21,20,6,15,1,14,1,21,20,22,51,50,54,55,21,14,1,35,34,36, +53,52,54,63,1,62,1,53,52,38,35,34,6,7,225,105,190,86,223,1,13,188,208,108,145,117,170,153,104,205,115,107,212,105,252,254,248,192,210,106,149,109,166,143,94,185,92,5,162,39,39,241,200,160,190,47,25,32,118,112,123,137,68,73,215,45,45,224,213,181,210,49, +24,35,104,99,113,133,60,59,0,1,0,213,255,227,4,6,4,123,0,39,0,0,1,62,1,51,50,22,21,20,6,15,2,6,21,20,22,51,50,54,55,21,14,1,35,34,38,53,52,54,63,1,62,1,53,52,38,35,34,6,7,1,14,80,166,90,202,218,146,159,69,8,245,134,122,84,188,103,106,182,83,210,236,141, +137,74,183,92,123,125,83,160,79,4,57,33,33,175,161,127,147,31,14,2,49,128,89,99,53,53,190,35,35,187,166,125,156,26,14,35,74,75,83,81,46,46,0,0,255,255,0,120,0,0,4,109,5,213,16,6,2,241,0,0,0,2,0,118,254,86,4,91,6,20,0,8,0,33,0,0,1,38,39,38,35,34,7,6,51, +5,3,20,23,22,59,1,21,35,34,39,38,53,17,35,32,53,52,33,50,23,22,23,51,21,2,56,7,18,33,110,124,3,3,119,1,120,2,39,37,100,176,174,195,81,87,190,254,242,1,47,181,82,53,18,191,5,4,45,23,48,65,51,154,251,61,103,41,40,153,86,92,180,4,174,210,216,96,64,111,155, +0,0,0,1,0,131,254,86,4,8,5,158,0,32,0,0,1,17,33,21,33,17,20,22,59,1,29,1,20,7,6,43,1,53,51,50,55,54,61,1,35,34,38,53,17,33,53,33,17,2,102,1,162,254,94,94,117,207,89,90,165,205,185,90,45,44,40,207,170,254,213,1,43,5,158,254,194,143,253,160,124,98,147, +20,195,105,106,156,62,62,126,20,166,203,2,96,143,1,62,0,0,0,0,1,0,47,0,0,4,162,5,213,0,16,0,0,1,38,7,6,29,1,35,53,52,54,51,33,21,33,17,35,17,1,197,131,70,49,156,192,214,2,221,254,45,203,5,47,8,55,38,114,49,70,181,163,170,250,213,5,43,0,0,1,0,131,0,0, +4,8,6,20,0,29,0,0,1,33,21,33,17,20,22,59,1,21,35,34,38,53,17,33,53,33,53,52,55,54,59,1,21,35,34,7,6,21,2,102,1,162,254,94,94,117,207,225,207,170,254,213,1,42,89,90,165,205,185,90,45,44,4,96,143,253,160,124,98,147,166,203,2,96,143,30,195,105,106,156,62, +62,126,0,0,0,0,1,0,47,254,86,4,162,5,213,0,17,0,0,19,33,21,33,17,20,23,22,59,1,21,35,34,39,38,53,17,33,47,4,115,254,45,44,45,90,185,223,165,90,89,254,43,5,213,170,250,193,126,62,62,156,106,105,195,5,63,0,0,0,255,255,0,9,255,227,4,200,6,25,16,39,2,163, +1,154,1,168,16,7,0,56,255,118,0,0,0,0,255,255,0,39,255,227,4,170,4,113,16,39,2,163,1,124,0,0,16,7,0,88,255,100,0,0,0,0,0,1,0,74,0,0,4,135,5,180,0,30,0,0,1,21,35,22,18,21,16,0,35,34,0,17,52,18,55,35,53,33,21,6,2,21,20,18,32,18,53,52,2,39,53,4,135,245, +123,110,254,224,240,242,254,223,111,123,248,1,207,120,134,180,1,52,179,134,120,5,180,172,134,254,224,188,254,201,254,145,1,110,1,56,188,1,33,133,172,172,76,254,183,222,230,254,247,1,9,230,222,1,73,76,172,0,0,0,0,1,0,154,0,0,4,42,5,213,0,24,0,0,33,34, +39,38,53,17,51,17,20,23,22,51,50,18,53,52,2,39,51,22,18,21,16,7,6,1,250,170,92,90,204,44,44,90,154,180,134,120,218,122,110,144,147,106,102,198,4,63,251,208,126,62,62,1,9,230,222,1,73,76,134,254,224,188,254,201,184,188,0,0,0,1,0,17,0,0,4,192,5,215,0,22, +0,0,1,3,17,35,17,1,51,1,19,54,55,54,51,50,31,1,7,39,38,35,34,7,6,3,107,246,183,254,83,193,1,72,199,99,109,46,45,80,75,25,71,10,34,40,28,31,51,4,116,254,42,253,98,2,158,3,55,253,109,1,145,200,42,18,57,19,134,9,31,16,24,0,0,0,0,1,0,24,254,86,4,201,4,109, +0,28,0,0,5,6,7,6,43,1,53,51,50,54,63,1,1,51,9,1,54,55,54,51,50,31,1,7,39,38,35,34,7,2,110,81,71,74,124,147,108,76,84,51,33,254,59,195,1,94,1,23,50,81,43,51,49,55,48,53,28,28,22,43,16,104,203,58,61,154,72,134,84,4,78,252,148,2,187,126,41,22,20,17,147, +10,11,41,0,0,0,1,0,156,0,0,4,145,5,213,0,18,0,0,19,33,21,1,51,21,33,35,1,33,21,33,53,1,35,53,33,1,33,178,3,201,254,117,232,254,247,80,254,240,3,34,252,11,1,19,180,1,34,1,118,253,31,5,213,154,253,176,170,254,105,170,154,1,167,170,2,64,0,1,0,156,0,0,4, +53,4,98,0,18,0,0,19,33,21,1,33,21,33,35,3,33,21,33,53,19,33,53,33,1,33,222,3,45,254,242,1,56,254,158,89,242,2,131,252,187,225,254,245,1,142,1,31,253,149,4,98,168,254,174,164,254,210,150,170,1,26,164,1,103,0,1,0,26,255,228,4,183,5,213,0,31,0,0,19,20,23, +22,32,55,54,53,52,39,38,43,1,53,1,33,53,33,21,1,50,23,22,23,22,21,20,4,33,32,36,53,228,100,99,1,123,100,100,92,94,164,174,1,114,253,30,3,202,254,136,104,130,98,86,80,254,208,254,232,254,220,254,208,1,179,143,75,75,75,75,143,134,73,74,166,1,185,170,168, +254,71,56,43,108,104,138,221,242,242,221,0,0,0,0,1,0,26,255,228,4,183,5,213,0,31,0,0,1,51,20,4,33,32,36,53,52,55,54,55,54,51,1,53,33,21,33,1,21,35,34,7,6,21,20,23,22,32,55,54,3,238,200,254,208,254,220,254,232,254,208,82,85,99,129,105,254,136,3,200,253, +32,1,114,174,166,92,92,100,99,1,123,100,100,1,179,221,242,242,221,138,104,108,43,56,1,185,168,170,254,71,166,74,73,134,143,75,75,75,75,0,0,0,1,0,125,254,76,4,84,4,96,0,32,0,0,9,1,53,33,21,33,1,21,35,34,7,6,21,20,23,22,51,50,54,55,21,6,7,6,35,32,36,53, +52,55,54,55,54,2,112,254,101,3,106,253,101,1,174,174,165,93,92,100,99,190,109,200,84,106,100,99,94,254,232,254,208,81,86,98,128,1,220,1,220,168,147,254,13,166,74,75,132,143,75,75,50,49,195,37,19,18,242,221,138,104,109,42,56,0,0,1,0,173,254,86,4,36,4, +96,0,32,0,0,1,50,55,54,55,21,6,7,6,35,32,17,52,37,36,53,52,35,48,33,1,33,53,33,21,1,32,21,16,5,6,21,20,2,187,84,77,79,81,87,80,86,97,254,32,1,150,1,28,235,254,222,1,229,253,101,3,106,254,158,1,111,254,48,226,254,238,21,21,44,179,32,13,14,1,25,238,53, +37,98,124,2,56,147,168,254,100,229,254,236,49,24,97,139,0,1,0,152,0,0,4,35,5,240,0,32,0,0,19,54,51,50,4,21,20,7,6,7,51,21,35,7,1,33,21,33,53,1,33,53,33,54,55,54,53,52,39,38,35,34,7,164,208,191,219,1,11,45,34,66,80,230,56,254,187,2,174,252,117,1,126,254, +229,1,178,105,30,22,150,57,68,181,222,5,141,99,233,189,96,96,74,85,170,63,254,168,170,170,1,151,170,130,84,60,62,185,60,22,133,0,0,0,0,1,0,26,255,228,4,182,5,213,0,32,0,0,37,32,55,54,53,52,39,38,35,33,17,33,21,33,17,33,50,23,22,23,22,21,20,4,33,32,3, +38,53,51,20,23,22,2,104,1,60,61,13,92,94,164,254,71,3,156,253,47,1,34,105,129,99,85,80,254,208,254,232,254,82,122,44,202,158,91,142,199,43,51,134,73,74,3,9,170,254,73,56,43,108,101,141,221,242,1,0,91,116,181,71,41,0,0,0,1,0,125,254,76,4,84,4,96,0,28, +0,0,1,32,55,54,53,52,39,38,35,33,17,33,21,33,17,55,54,23,22,23,22,21,20,4,33,34,39,53,22,2,6,1,55,63,15,92,93,165,254,212,2,240,253,200,168,103,131,99,85,81,254,208,254,232,187,212,170,254,246,195,45,53,134,73,74,3,44,184,254,51,1,1,57,43,108,104,138, +221,242,74,195,99,0,1,0,194,255,227,4,15,5,158,0,32,0,0,1,52,39,38,43,1,17,35,53,51,17,51,17,51,21,35,21,22,23,22,21,20,7,6,33,34,39,53,22,51,50,55,54,3,77,74,89,173,62,229,229,202,231,231,165,108,117,110,138,254,238,171,152,156,159,179,99,57,1,183,114, +79,95,1,15,164,1,20,254,236,164,125,29,110,119,176,185,126,157,70,172,86,114,65,0,0,0,2,0,125,254,86,4,103,4,123,0,14,0,23,0,0,5,17,35,17,51,21,54,55,54,51,50,23,22,21,16,1,0,53,52,39,38,35,34,7,1,54,185,185,52,135,81,210,184,77,78,252,207,2,114,57,56, +120,220,173,122,254,208,6,10,170,66,82,49,112,113,153,254,87,254,228,1,144,249,133,66,65,239,0,0,1,2,3,0,0,2,206,5,213,0,3,0,0,1,51,17,35,2,4,202,202,5,213,250,43,0,0,255,255,1,57,0,0,3,152,5,213,16,39,1,130,255,54,0,0,16,7,1,130,0,202,0,0,0,0,0,1,0, +164,0,0,4,45,5,213,0,19,0,0,1,51,17,33,21,33,21,33,21,33,17,35,17,33,53,33,53,33,53,33,2,4,202,1,94,254,162,1,94,254,162,202,254,160,1,96,254,160,1,96,5,213,254,108,168,240,170,254,1,1,255,170,240,168,255,255,2,3,0,0,2,206,5,213,16,6,0,4,255,0,255,255, +0,37,0,0,4,172,7,109,16,38,0,36,0,0,16,7,13,3,0,0,1,117,255,255,0,133,255,227,4,35,6,102,16,38,0,68,0,0,16,6,2,104,0,0,0,0,255,255,0,201,0,0,4,6,7,109,16,38,0,44,0,0,16,7,13,3,0,0,1,117,255,255,0,178,0,0,4,68,6,102,16,38,0,243,0,0,16,6,2,104,0,0,0,0, +255,255,0,117,255,227,4,92,7,109,16,38,0,50,0,0,16,7,13,3,0,0,1,117,255,255,0,137,255,227,4,72,6,102,16,38,0,82,0,0,16,6,2,104,0,0,0,0,255,255,0,147,255,227,4,61,7,109,16,38,0,56,0,0,17,7,13,3,0,0,1,117,0,20,180,17,35,31,1,7,43,64,9,32,31,47,35,0,31, +15,35,4,93,49,0,0,255,255,0,195,255,227,4,27,6,102,16,38,0,88,0,0,16,6,2,104,0,0,0,0,255,255,0,147,255,227,4,61,7,160,16,39,12,254,0,0,0,249,16,38,0,56,0,0,16,7,2,106,0,0,1,170,255,255,0,195,255,227,4,27,7,50,16,38,2,144,0,0,16,38,0,88,0,0,16,7,0,113, +0,0,1,60,0,0,255,255,0,147,255,227,4,61,7,249,16,39,12,254,0,0,0,249,16,38,0,56,0,0,16,7,12,255,0,0,2,3,255,255,0,195,255,227,4,27,7,162,16,38,2,144,0,0,16,38,0,88,0,0,16,7,2,137,0,0,1,60,0,0,255,255,0,147,255,227,4,61,7,251,16,39,12,254,0,0,0,249,16, +38,0,56,0,0,16,7,13,3,0,0,2,3,255,255,0,195,255,227,4,27,7,162,16,38,2,144,0,0,16,38,0,88,0,0,16,7,2,148,0,0,1,60,0,0,255,255,0,147,255,227,4,61,7,249,16,39,12,254,0,0,0,249,16,38,0,56,0,0,16,7,13,1,0,0,2,3,255,255,0,195,255,227,4,27,7,162,16,39,2,136, +0,0,1,60,16,6,0,190,0,0,255,255,0,122,255,227,4,87,4,123,18,6,1,255,0,0,255,255,0,37,0,0,4,172,7,160,16,39,12,254,0,0,0,249,16,39,2,106,0,0,1,170,16,6,0,36,0,0,255,255,0,133,255,227,4,35,7,50,16,39,0,113,0,0,1,60,16,6,0,166,0,0,255,255,0,37,0,0,4,172, +7,160,16,39,2,106,0,0,1,170,16,38,13,7,0,132,16,6,0,36,0,0,0,0,255,255,0,133,255,227,4,35,7,50,16,39,0,113,0,0,1,60,18,6,1,214,0,0,255,255,0,0,0,0,4,156,7,48,16,39,13,11,0,170,0,0,16,6,0,136,0,0,255,255,0,41,255,227,4,176,5,246,16,38,2,140,0,0,16,6,0, +168,0,0,0,0,255,255,0,102,255,227,4,80,7,109,16,39,13,3,0,0,1,117,16,6,0,42,0,0,255,255,0,123,254,72,4,18,6,102,16,38,2,104,0,0,16,6,0,74,0,0,0,0,255,255,0,137,0,0,4,201,7,109,16,39,13,3,0,0,1,117,16,6,0,46,0,0,255,255,0,236,0,0,4,178,7,109,16,39,13, +3,0,0,1,117,16,6,0,78,0,0,255,255,0,117,254,101,4,92,5,240,16,38,2,120,28,240,16,6,0,50,0,0,0,0,255,255,0,137,254,101,4,72,4,123,16,38,2,120,28,240,16,6,0,82,0,0,0,0,255,255,0,117,254,101,4,92,7,48,16,38,13,11,0,0,16,6,1,161,0,0,0,0,255,255,0,137,254, +101,4,72,5,246,16,38,2,140,0,0,16,6,1,162,0,0,0,0,255,255,0,26,255,228,4,183,7,109,16,39,13,3,0,0,1,117,16,6,1,121,0,0,255,255,0,125,254,76,4,84,6,102,16,38,2,104,0,0,16,6,2,56,0,0,0,0,255,255,0,186,254,86,3,203,6,97,16,38,2,104,35,251,16,6,1,230,0,0, +0,0,255,255,0,102,255,227,4,80,7,107,16,39,12,255,0,90,1,117,16,6,0,42,0,0,255,255,0,123,254,72,4,18,6,102,16,38,0,118,0,0,16,6,0,74,0,0,0,0,0,1,0,61,255,227,4,148,5,213,0,29,0,0,37,50,55,54,25,1,51,17,16,7,6,35,34,39,38,17,53,33,17,35,17,51,17,33,17, +51,17,16,23,22,3,109,54,25,33,182,104,57,133,128,72,134,254,213,182,182,1,43,183,82,23,135,79,102,1,14,1,39,254,192,254,139,140,77,83,153,1,98,150,253,57,5,213,253,156,2,100,252,117,254,239,139,39,0,0,0,255,255,0,139,0,0,4,70,7,107,16,39,13,1,0,0,1,117, +16,6,0,49,0,0,255,255,0,195,0,0,4,27,6,102,16,38,0,67,0,0,16,6,0,81,0,0,0,0,255,255,0,0,0,0,4,156,7,107,16,39,12,255,0,240,1,117,16,6,0,136,0,0,255,255,0,41,255,227,4,176,6,102,16,38,0,118,0,0,16,6,0,168,0,0,0,0,255,255,0,8,255,186,4,176,7,107,16,39, +12,255,0,0,1,117,16,6,0,154,0,0,255,255,0,47,255,160,4,150,6,102,16,38,0,118,0,0,16,6,0,186,0,0,0,0,255,255,0,37,0,0,4,172,7,107,16,38,13,9,0,0,16,6,0,36,0,0,0,0,255,255,0,133,255,227,4,35,6,102,16,38,2,151,0,0,16,6,0,68,0,0,0,0,255,255,0,37,0,0,4,172, +7,109,16,38,13,5,0,0,16,6,0,36,0,0,0,0,255,255,0,133,255,227,4,35,6,72,16,38,2,153,0,0,16,6,0,68,0,0,0,0,255,255,0,187,0,0,4,78,7,107,16,38,13,9,0,0,16,6,0,40,0,0,0,0,255,255,0,123,255,227,4,88,6,102,16,38,2,151,14,0,16,6,0,72,0,0,0,0,255,255,0,197,0, +0,4,78,7,109,16,38,13,5,0,0,16,6,0,40,0,0,0,0,255,255,0,123,255,227,4,88,6,72,16,38,2,153,14,0,16,6,0,72,0,0,0,0,255,255,0,187,0,0,4,6,7,107,16,38,13,9,0,0,16,6,0,44,0,0,0,0,255,255,0,178,0,0,4,68,6,102,16,38,2,151,0,0,16,6,0,243,0,0,0,0,255,255,0,201, +0,0,4,6,7,109,16,38,13,5,0,0,16,6,0,44,0,0,0,0,255,255,0,178,0,0,4,68,6,72,16,38,2,153,0,0,16,6,0,243,0,0,0,0,255,255,0,117,255,227,4,92,7,107,16,38,13,9,0,0,16,6,0,50,0,0,0,0,255,255,0,137,255,227,4,72,6,102,16,38,2,151,0,0,16,6,0,82,0,0,0,0,255,255, +0,117,255,227,4,92,7,109,16,38,13,5,0,0,16,6,0,50,0,0,0,0,255,255,0,137,255,227,4,72,6,72,16,38,2,153,0,0,16,6,0,82,0,0,0,0,255,255,0,137,0,0,4,209,7,107,16,38,13,9,206,0,16,6,0,53,0,0,0,0,255,255,1,104,0,0,4,131,6,102,16,39,2,151,0,150,0,0,16,6,0,85, +0,0,255,255,0,143,0,0,4,209,7,109,16,38,13,5,206,0,16,6,0,53,0,0,0,0,255,255,1,106,0,0,4,131,6,72,16,39,2,153,0,150,0,0,16,6,0,85,0,0,255,255,0,147,255,227,4,61,7,107,16,38,13,9,0,0,16,6,0,56,0,0,0,0,255,255,0,195,255,227,4,27,6,102,16,38,2,151,0,0,16, +6,0,88,0,0,0,0,255,255,0,147,255,227,4,61,7,109,16,38,13,5,0,0,16,6,0,56,0,0,0,0,255,255,0,195,255,227,4,27,6,72,16,38,2,153,0,0,16,6,0,88,0,0,0,0,255,255,0,139,253,226,4,74,5,240,16,38,2,174,0,0,16,6,0,54,0,0,0,0,255,255,0,213,253,226,4,6,4,123,16,38, +2,174,0,0,16,6,0,86,0,0,0,0,255,255,0,47,253,226,4,162,5,213,16,38,2,174,0,0,16,6,0,55,0,0,0,0,255,255,0,131,253,226,4,8,5,158,16,38,2,174,89,0,16,6,0,87,0,0,0,0,0,1,0,125,254,82,4,84,5,240,0,46,0,0,1,4,17,20,14,1,12,1,7,53,54,36,62,1,53,52,38,35,34, +15,1,53,55,62,3,53,52,46,3,35,34,7,53,54,51,50,30,1,21,20,14,2,3,32,1,52,111,185,255,0,254,234,153,200,1,49,185,92,125,112,95,115,163,248,60,102,104,61,35,55,75,72,38,184,243,239,206,131,203,124,23,58,110,2,162,67,254,219,112,206,160,136,96,34,160,55, +140,153,157,79,101,132,51,72,171,106,26,65,99,139,82,55,86,51,34,12,184,190,164,86,182,128,60,102,113,116,0,1,0,174,254,79,4,35,4,123,0,52,0,0,1,30,3,21,20,14,5,7,53,62,4,53,52,38,35,34,15,1,53,55,62,4,53,52,46,3,35,34,6,7,53,36,51,50,30,1,21,20,6,3, +14,70,112,62,33,66,108,152,157,179,149,74,162,245,158,99,40,118,93,59,63,216,223,34,65,87,63,45,31,49,67,65,35,69,168,147,1,10,134,112,184,116,103,1,205,8,68,90,88,37,75,138,108,97,70,61,39,15,130,46,96,91,98,91,51,88,112,25,86,139,85,13,32,60,69,102, +57,44,70,42,27,10,59,90,154,133,71,146,97,110,153,0,0,0,255,255,0,137,0,0,4,72,7,109,16,39,13,3,0,0,1,117,16,6,0,43,0,0,255,255,0,195,0,0,4,27,7,109,16,39,13,3,0,0,1,117,16,6,0,75,0,0,0,1,0,147,254,82,4,61,5,242,0,19,0,0,1,17,35,17,52,38,35,34,6,21,17, +35,17,51,21,62,1,51,50,18,4,61,203,116,124,141,152,202,202,54,184,126,187,185,3,231,250,107,5,159,180,169,218,203,252,87,5,213,198,111,116,254,251,0,0,3,0,18,255,108,4,159,6,20,0,6,0,40,0,49,0,0,37,22,55,50,55,54,34,39,20,23,54,55,54,21,16,35,34,39,6, +7,35,55,38,47,1,6,7,6,39,38,39,38,17,16,18,51,50,22,23,17,51,0,16,22,50,54,53,52,38,34,3,109,12,66,123,3,4,128,169,13,114,104,164,250,71,48,30,20,119,68,32,38,16,28,56,77,100,163,92,93,187,161,80,123,35,184,253,153,108,212,111,111,212,144,18,1,155,62, +62,116,35,244,1,2,218,254,199,17,79,57,194,13,89,37,90,53,72,1,2,155,158,1,21,1,17,1,55,87,83,2,67,252,241,254,84,218,220,212,213,219,0,0,0,1,0,156,254,86,4,146,5,213,0,23,0,0,19,33,21,1,33,21,51,21,20,7,6,43,1,53,51,50,55,54,61,1,33,53,1,33,178,3,201, +252,244,3,34,1,89,90,165,205,185,90,45,44,252,195,2,247,253,31,5,213,154,251,111,42,148,195,105,106,156,62,62,126,20,154,4,145,0,0,0,1,0,203,254,86,4,16,4,98,0,23,0,0,19,33,21,1,33,21,35,21,20,7,6,43,1,53,51,50,55,54,61,1,33,53,1,33,227,3,45,253,125, +2,131,8,89,90,165,205,185,90,45,44,253,124,2,131,253,149,4,98,168,252,220,150,20,195,105,106,156,62,62,126,20,170,3,37,0,0,255,255,0,37,0,0,4,172,7,80,16,38,13,7,0,0,16,6,0,36,0,0,0,0,255,255,0,133,255,227,4,35,6,16,16,38,2,143,0,0,16,6,0,68,0,0,0,0, +255,255,0,197,254,117,4,78,5,213,16,38,2,175,50,0,16,6,0,40,0,0,0,0,255,255,0,123,254,117,4,88,4,123,16,38,2,175,50,0,16,6,0,72,0,0,0,0,255,255,0,117,255,227,4,92,7,160,16,39,12,254,0,0,0,249,16,39,2,106,0,0,1,170,16,6,0,50,0,0,255,255,0,137,255,227, +4,72,7,50,16,39,0,113,0,0,1,60,16,6,0,184,0,0,255,255,0,117,255,227,4,92,7,160,16,38,0,50,0,0,16,39,13,0,0,0,0,245,16,7,2,106,0,0,1,170,255,255,0,137,255,227,4,72,7,50,16,39,0,113,0,4,1,60,16,6,0,183,0,0,255,255,0,117,255,227,4,92,7,80,16,38,13,7,0,0, +16,6,0,50,0,0,0,0,255,255,0,137,255,227,4,72,6,16,16,38,2,143,0,0,16,6,0,82,0,0,0,0,255,255,0,117,255,227,4,92,7,160,16,39,2,106,0,0,1,170,16,38,13,7,0,132,16,6,0,50,0,0,0,0,255,255,0,137,255,227,4,72,7,50,16,39,0,113,0,0,1,60,16,6,1,222,0,0,255,255, +0,37,0,0,4,172,7,48,16,38,13,11,0,0,16,6,0,60,0,0,0,0,255,255,0,104,254,86,4,129,5,246,16,38,2,140,0,0,16,6,0,92,0,0,0,0,0,2,0,160,255,108,4,10,6,31,0,6,0,29,0,0,37,22,55,50,55,54,34,3,6,7,35,55,38,39,38,53,17,33,53,33,17,20,23,54,55,54,21,16,35,34,2, +216,12,66,123,3,4,128,144,29,20,119,68,19,51,39,254,217,1,223,13,114,104,164,250,70,144,18,1,155,62,254,156,79,57,194,5,97,74,184,3,249,144,251,119,116,35,244,1,2,218,254,199,0,0,2,0,106,255,108,4,102,4,123,0,6,0,46,0,0,37,22,55,50,55,54,34,39,20,23, +54,55,54,23,20,21,16,7,34,39,6,7,35,55,38,39,38,61,1,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,23,22,17,3,52,12,66,123,3,4,128,185,22,122,103,159,5,250,71,49,29,20,119,68,19,51,39,53,90,73,57,167,167,33,99,63,133,57,56,144,18,1,155,62,62,114,46,252, +2,2,206,6,6,254,200,1,17,79,57,194,5,97,74,184,235,237,115,123,229,253,127,4,96,96,60,63,105,101,254,220,0,2,0,131,255,108,4,8,5,158,0,6,0,35,0,0,37,22,55,50,55,54,34,39,20,23,54,55,54,21,16,35,34,39,6,7,35,55,38,39,38,53,17,33,53,33,17,51,17,33,21,33, +2,191,12,66,123,3,4,128,169,13,114,104,164,250,71,48,30,20,119,68,19,51,39,254,213,1,43,184,1,162,254,94,144,18,1,155,62,62,116,35,244,1,2,218,254,199,17,79,57,194,5,97,74,184,2,59,143,1,62,254,194,143,0,0,0,1,0,186,254,86,3,16,4,96,0,13,0,44,64,22,5, +0,1,10,140,8,1,182,3,194,8,195,14,11,8,2,9,2,4,6,0,14,16,212,236,196,196,18,57,57,49,0,16,228,244,238,16,238,17,57,57,48,5,17,33,53,33,17,20,6,43,1,53,51,50,54,2,88,254,195,1,245,179,165,254,234,90,90,20,3,229,143,251,140,195,211,156,125,0,0,0,3,0,120, +255,227,4,89,6,20,0,8,0,19,0,49,0,0,18,16,22,50,54,53,52,38,34,0,16,38,35,34,6,21,20,22,51,50,3,62,1,51,50,18,17,16,2,35,34,38,39,21,35,53,14,1,35,34,2,17,16,18,51,50,22,23,17,51,237,81,160,83,83,160,2,166,81,80,81,82,82,81,80,243,26,93,61,122,139,140, +122,60,92,27,111,27,92,60,122,140,141,121,60,93,26,111,3,5,254,84,218,220,212,213,219,253,122,1,172,218,219,213,212,220,3,82,82,88,254,201,254,239,254,235,254,197,87,83,141,141,83,87,1,59,1,21,1,17,1,55,87,83,2,67,0,0,0,3,0,120,254,74,4,89,4,123,0,8, +0,19,0,49,0,0,0,16,38,34,6,21,20,22,50,0,16,22,51,50,54,53,52,38,35,34,19,14,1,35,34,2,17,16,18,51,50,22,23,53,51,21,62,1,51,50,18,17,16,2,35,34,38,39,17,35,3,228,81,160,83,83,160,253,90,81,80,80,83,83,80,80,243,26,93,61,121,140,140,122,60,92,27,111, +27,92,60,122,140,141,121,61,92,26,111,1,89,1,172,218,220,212,213,219,2,134,254,84,218,219,213,212,220,252,174,82,88,1,55,1,17,1,21,1,59,87,83,141,141,83,87,254,197,254,235,254,239,254,201,87,83,253,189,0,0,3,0,8,255,186,4,176,6,23,0,15,0,18,0,21,0,0, +1,51,19,1,23,9,1,35,3,33,15,1,35,7,39,55,1,33,3,39,11,1,1,238,245,96,1,9,100,254,193,1,59,209,110,254,67,130,56,86,49,103,52,1,230,1,27,81,43,89,207,5,213,254,199,1,123,74,254,56,251,251,1,133,186,203,70,70,74,1,221,1,33,155,1,64,253,25,0,2,0,8,255,186, +4,176,6,23,0,8,0,41,0,0,9,1,39,38,35,34,2,17,20,1,14,1,35,32,47,1,7,39,19,38,17,16,0,33,50,23,22,23,55,23,7,21,38,39,1,22,23,22,51,50,54,55,1,112,2,52,18,85,86,197,196,2,211,77,162,91,254,225,158,9,178,103,212,81,1,63,1,29,91,81,59,56,70,100,127,16,17, +253,139,16,21,98,197,88,169,73,2,2,3,36,6,32,254,208,254,205,126,253,202,41,41,203,11,255,70,1,47,179,1,7,1,110,1,153,20,15,26,100,74,181,73,13,12,252,126,39,32,152,64,61,0,0,0,2,0,47,255,160,4,150,4,188,0,7,0,40,0,0,9,1,38,35,34,6,21,20,1,14,1,35,32, +47,1,7,39,19,38,53,16,0,33,50,23,22,23,55,23,7,21,38,39,1,22,23,22,51,50,54,55,1,149,1,220,62,71,173,186,2,160,74,157,82,254,252,146,8,195,92,216,68,1,37,1,4,81,77,40,40,95,93,113,34,33,253,228,13,15,94,172,96,152,65,1,150,2,55,18,224,208,83,254,93,43, +43,156,9,232,76,1,2,132,189,1,20,1,56,21,11,17,114,77,134,133,30,22,253,127,21,18,113,59,62,0,1,0,21,0,0,4,188,5,213,0,13,0,0,1,51,17,33,21,33,17,33,21,33,17,33,53,33,1,32,203,1,7,254,249,2,209,252,100,254,245,1,11,5,213,253,22,170,254,105,170,2,65,170, +0,0,0,2,0,33,255,186,4,201,6,23,0,2,0,18,0,0,1,19,35,3,17,33,53,33,55,23,7,21,35,1,17,35,17,1,39,2,205,243,243,203,254,45,4,8,46,100,39,74,254,117,203,254,134,103,3,208,1,91,253,132,2,124,170,66,74,56,106,253,205,253,8,1,214,253,228,70,0,1,0,213,254, +16,4,25,4,123,0,53,0,0,1,21,46,1,35,34,6,21,20,22,31,1,30,1,21,20,7,6,7,31,1,22,51,21,35,34,39,38,47,1,38,47,1,53,54,23,22,51,50,54,53,52,47,2,38,39,38,53,52,54,51,50,22,3,205,79,160,83,125,123,92,183,74,137,141,118,104,176,152,147,42,76,39,84,114,71, +89,237,51,101,50,123,122,68,62,122,134,245,8,69,161,71,73,218,202,90,166,4,57,180,46,46,81,83,75,74,35,14,26,156,125,166,94,82,10,152,126,36,154,61,38,91,243,53,35,16,190,5,96,15,99,89,128,49,2,14,33,71,74,127,161,175,33,0,0,0,0,1,0,203,254,16,4,16,4, +98,0,23,0,0,19,33,21,1,22,23,1,23,22,59,1,21,35,34,39,38,47,1,38,35,61,1,1,33,227,3,45,253,106,49,32,1,8,147,42,76,52,91,84,114,71,89,237,61,90,2,131,253,149,4,98,168,252,203,17,32,254,248,126,36,154,61,38,91,243,63,156,14,3,37,0,1,0,55,0,0,4,154,5,213, +0,26,0,0,1,34,7,6,29,1,35,53,52,54,51,33,50,4,21,20,4,35,17,35,17,51,50,54,16,38,35,1,118,54,60,48,156,192,126,1,39,250,1,2,254,255,251,202,202,140,157,156,141,5,47,47,38,114,49,70,181,163,227,219,221,226,253,168,2,254,148,1,10,147,0,3,0,8,0,0,4,113, +5,213,0,18,0,27,0,40,0,0,19,33,50,22,21,20,6,7,30,1,21,20,4,41,1,17,35,53,51,19,17,51,50,54,53,52,38,35,3,21,51,50,54,53,52,38,43,1,21,51,21,166,1,186,229,248,131,131,147,167,254,246,254,249,254,70,158,158,203,235,146,131,129,148,235,239,176,150,158, +168,239,235,5,213,198,181,137,158,20,22,207,160,203,207,1,110,149,3,44,254,62,112,125,113,100,252,63,200,123,141,146,137,198,149,0,0,0,2,0,21,255,227,4,188,5,213,0,26,0,41,0,0,19,53,51,17,51,17,33,17,51,17,51,21,35,21,20,6,7,14,1,35,34,38,39,46,1,61, +1,41,1,21,20,22,23,30,1,51,50,54,55,62,1,53,21,126,203,2,21,202,127,127,57,70,66,170,106,105,170,67,69,58,2,224,253,235,12,15,32,121,86,87,120,33,15,12,2,65,170,2,234,253,22,2,234,253,22,170,4,229,193,63,59,58,58,59,62,197,226,4,96,109,93,25,59,60,60, +59,25,92,108,0,0,0,0,1,0,57,0,0,4,152,5,213,0,6,0,0,9,1,35,1,51,1,35,2,105,254,161,209,1,181,245,1,181,209,5,43,250,213,5,213,250,43,0,2,0,21,0,0,4,209,5,213,0,24,0,33,0,0,19,33,50,4,21,20,6,7,22,23,22,23,19,35,3,46,1,43,1,17,35,17,35,53,51,19,17,51, +50,54,53,52,38,35,227,1,76,246,1,6,161,146,78,55,54,83,203,217,178,77,123,99,109,203,206,206,203,137,145,142,151,144,5,213,222,210,148,187,21,20,55,55,167,254,104,1,121,161,93,253,137,2,119,166,2,18,253,238,130,134,129,137,0,1,0,142,0,0,4,131,4,123,0, +25,0,0,1,46,1,35,34,7,6,7,33,21,33,17,35,17,35,53,51,17,51,21,62,1,51,50,22,23,4,131,59,122,73,172,91,77,12,2,1,253,253,185,220,220,185,46,191,131,68,118,54,3,121,46,42,108,92,161,164,254,60,1,196,164,1,248,219,119,127,34,36,0,0,2,0,154,255,227,4,56, +4,123,0,11,0,41,0,0,1,51,50,54,53,52,38,35,34,6,29,1,7,17,51,21,62,1,51,50,22,21,20,6,43,1,21,20,22,51,50,54,55,21,14,1,35,34,38,39,46,1,1,254,62,160,164,122,108,152,176,184,184,60,178,128,172,204,252,242,248,136,146,94,192,92,102,188,88,138,198,60,38, +32,2,43,113,112,101,112,211,186,41,76,2,127,166,100,95,193,162,187,194,29,134,121,54,52,184,39,39,82,82,50,147,0,0,0,0,2,0,123,255,227,4,18,4,123,0,16,0,28,0,48,64,26,5,0,20,26,140,14,20,140,8,153,14,190,1,194,3,23,4,0,6,2,71,17,18,11,72,29,16,244,236, +252,236,50,50,49,0,47,236,228,244,236,16,238,17,57,57,48,1,53,51,17,35,53,14,1,35,34,2,17,16,18,51,50,22,1,20,22,51,50,54,53,52,38,35,34,6,3,90,184,184,46,153,100,203,233,234,202,101,154,254,15,136,133,133,139,139,133,133,136,3,209,141,251,162,141,83, +87,1,59,1,21,1,17,1,55,87,254,11,214,218,220,212,213,219,218,0,0,0,2,0,192,255,225,4,87,4,121,0,11,0,28,0,48,64,26,24,12,9,3,140,15,9,140,21,153,15,190,27,194,25,0,18,18,71,24,12,6,6,26,70,29,16,244,236,50,50,252,236,49,0,47,236,228,244,236,16,238,17, +57,57,48,1,52,38,35,34,6,21,20,22,51,50,54,1,62,1,51,50,18,17,16,2,35,34,38,39,21,35,17,51,3,149,136,133,133,139,139,133,133,136,253,227,46,153,100,203,233,234,202,101,154,44,184,184,2,45,214,218,220,212,213,219,218,2,120,83,87,254,197,254,235,254,239, +254,201,87,83,139,4,94,0,0,2,0,193,255,227,4,88,6,20,0,11,0,36,0,57,64,31,3,140,12,15,9,140,24,21,153,15,190,25,33,140,30,155,25,0,18,18,71,30,33,31,24,12,6,6,26,70,37,16,252,236,50,50,196,57,57,244,236,49,0,47,252,236,16,228,244,196,236,16,198,238,48, +1,52,38,35,34,6,21,20,22,51,50,54,1,62,1,51,50,18,17,16,2,35,34,38,39,21,35,17,52,54,59,1,21,35,34,6,21,3,150,136,133,134,138,138,134,133,136,253,227,44,155,102,202,232,233,203,100,153,46,184,179,165,204,184,90,90,2,47,214,218,219,213,212,220,218,2,120, +82,88,254,201,254,239,254,235,254,197,87,83,141,4,126,195,211,156,125,125,0,0,0,1,0,184,255,227,4,26,4,123,0,25,0,48,64,6,19,18,6,0,12,26,16,220,60,212,236,49,0,64,19,0,139,25,192,22,12,139,13,192,16,140,9,22,140,3,190,9,153,26,16,228,244,236,16,254, +244,238,16,245,238,48,19,62,1,51,32,0,17,16,0,33,34,38,39,53,30,1,51,50,54,53,52,38,35,34,6,7,184,74,156,82,1,4,1,38,254,218,254,252,80,154,78,72,148,92,174,186,188,172,96,152,64,4,37,43,43,254,200,254,236,254,236,254,200,42,44,193,65,58,224,208,207, +225,59,62,0,2,0,195,255,115,4,58,4,123,0,33,0,41,0,0,5,52,55,38,39,38,17,16,0,33,50,22,23,21,46,1,35,34,6,21,20,23,22,23,54,51,32,21,20,33,34,39,6,21,19,22,51,50,53,52,35,34,1,180,13,57,48,149,1,37,1,4,81,154,78,73,147,93,173,186,99,7,6,85,195,1,45,254, +178,82,71,6,43,60,74,146,132,101,141,104,81,35,51,161,1,12,1,20,1,56,42,44,193,65,58,224,208,220,99,7,7,176,246,189,17,57,68,1,31,19,57,75,0,2,0,123,254,86,4,56,6,20,0,8,0,36,0,0,0,16,22,50,54,53,52,38,34,5,17,51,17,20,23,22,59,1,21,35,34,39,38,61,1, +6,7,6,35,34,2,17,16,18,51,50,22,1,60,109,213,112,112,213,1,69,181,35,36,72,6,56,132,72,71,37,61,61,80,180,207,208,179,81,123,3,5,254,84,218,220,212,213,219,14,2,67,249,216,126,62,62,156,106,105,195,161,83,44,43,1,59,1,21,1,17,1,55,87,0,0,2,0,123,255, +227,4,55,6,20,0,10,0,38,0,0,0,16,22,51,50,54,53,52,38,35,34,37,53,52,55,54,59,1,21,35,34,7,6,21,17,35,53,14,1,35,34,2,17,16,18,51,50,22,23,1,59,109,106,107,111,111,107,106,1,68,71,72,132,56,5,72,36,35,183,36,123,80,180,206,207,179,81,123,35,3,5,254,84, +218,220,212,213,219,11,148,195,105,106,156,62,62,126,251,130,141,83,87,1,59,1,21,1,17,1,55,87,83,0,0,0,2,0,122,255,227,4,87,4,123,0,21,0,28,0,0,19,52,18,51,50,0,17,16,0,33,34,38,39,53,30,1,51,50,54,61,1,33,55,33,46,1,35,34,6,122,247,214,240,1,32,254, +218,254,251,91,195,105,109,192,88,174,191,252,227,184,2,94,16,172,133,136,149,2,94,251,1,34,254,192,254,244,254,237,254,199,43,43,183,57,56,200,183,6,143,156,176,170,0,0,0,2,0,122,255,227,4,87,4,123,0,21,0,28,0,63,64,12,3,2,28,18,16,73,9,22,6,0,72,29, +16,244,236,196,244,236,57,57,49,0,64,22,0,22,3,1,10,139,9,141,6,140,13,190,29,22,182,1,193,25,140,19,153,29,16,244,236,244,238,16,244,244,244,238,18,57,17,57,48,19,53,33,53,52,38,35,34,6,7,53,62,1,51,32,0,17,16,0,35,34,2,55,20,22,51,50,54,55,122,3,29, +191,174,88,192,109,105,195,91,1,5,1,38,254,224,240,214,247,184,149,136,133,172,16,2,0,90,6,183,200,56,57,183,43,43,254,199,254,237,254,244,254,192,1,34,198,162,170,176,156,0,2,0,30,255,227,4,179,4,123,0,9,0,41,0,0,37,54,53,52,39,1,22,23,22,50,3,50,23, +55,51,21,20,22,59,1,21,35,34,38,53,7,22,21,16,2,32,39,38,39,1,38,39,38,32,7,53,54,2,66,76,7,254,43,23,25,62,231,151,252,119,154,140,57,80,33,49,132,129,106,23,226,254,148,99,71,20,2,70,15,20,58,254,194,147,154,214,138,207,62,56,254,156,69,35,90,3,252, +232,117,148,153,97,156,186,200,81,96,118,254,237,254,189,145,103,156,1,187,40,34,99,104,174,86,0,0,0,1,0,169,255,234,4,40,4,123,0,48,0,57,64,31,11,140,12,16,140,7,190,50,27,182,23,50,38,140,37,33,140,42,153,50,24,11,38,19,18,4,29,18,46,70,49,16,252,236, +212,236,212,196,196,49,0,16,244,236,212,236,16,212,236,16,244,236,212,236,48,1,38,39,38,53,52,54,51,50,23,22,23,21,38,39,38,35,34,6,21,20,23,22,59,1,21,35,34,6,21,20,23,22,51,50,55,54,55,21,6,7,6,35,34,39,38,53,52,54,1,193,119,65,64,244,209,81,91,92, +105,104,87,86,76,138,148,72,72,135,166,159,150,168,90,91,173,99,91,91,77,97,90,91,86,254,139,138,148,2,95,25,65,64,94,134,158,12,12,24,167,27,13,12,86,74,61,43,44,144,110,81,98,53,52,18,17,34,173,28,14,14,91,92,166,109,148,0,0,0,0,1,0,169,255,234,4,40, +4,123,0,40,0,60,64,33,32,139,31,192,28,140,35,190,41,0,20,182,21,41,9,139,10,192,13,140,6,153,41,25,18,38,16,18,3,21,32,10,41,16,220,196,196,212,236,212,236,49,0,16,244,252,252,236,16,212,236,57,16,244,252,253,238,48,1,30,1,21,20,4,35,34,38,39,53,30, +1,51,50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,3,15,132,149,254,235,255,85,182,96,76,182,100,173,181,169,150,158,165,136,144,149,138,75,173,104,105,183,80,210,244,130,2,95,23,148,109,166,183,28,28,173,34,35,105,98,81, +110,144,87,61,74,86,25,27,167,24,24,158,134,94,129,0,0,0,0,1,0,56,255,234,4,153,4,123,0,66,0,0,1,22,23,22,21,20,7,6,35,34,38,39,53,22,23,22,51,50,55,54,53,52,39,38,43,1,53,51,50,55,54,53,52,39,38,35,34,7,6,7,53,54,55,54,51,50,23,22,23,55,51,21,20,23, +22,59,1,21,35,34,39,38,53,7,53,7,6,2,5,99,56,56,104,104,191,64,136,72,57,68,68,75,130,67,69,64,63,113,118,124,102,54,54,56,56,104,56,65,65,78,79,68,69,60,158,91,75,14,169,138,29,28,79,32,48,131,65,61,211,5,49,2,95,23,74,74,109,166,92,91,28,28,173,34, +17,18,52,53,98,81,55,55,144,44,43,61,74,43,43,12,13,27,167,24,12,12,79,65,102,131,148,153,49,48,156,96,90,200,162,1,6,65,0,0,0,2,0,176,255,213,4,34,4,121,0,20,0,40,0,0,1,32,17,16,33,50,55,54,53,52,39,38,43,1,53,51,50,55,54,52,38,37,54,51,50,22,21,20, +6,7,30,1,21,20,6,35,34,39,36,17,16,2,158,254,173,1,83,118,60,59,59,33,139,136,136,139,33,59,121,254,177,85,161,160,201,107,98,98,107,203,160,159,85,254,237,3,216,254,94,254,65,59,59,76,76,54,30,157,30,55,154,115,115,46,173,148,103,142,27,28,142,103,148, +174,61,194,1,88,1,138,0,0,0,1,0,186,254,86,4,113,4,94,0,21,0,0,1,21,33,17,20,6,43,1,53,51,50,54,53,17,33,53,33,17,33,53,33,17,4,113,254,159,179,165,254,234,90,90,254,129,1,127,254,195,1,245,2,104,164,254,40,195,211,156,125,125,1,216,164,1,103,143,254, +10,0,2,0,123,254,72,4,52,6,20,0,38,0,48,0,0,1,53,52,55,54,59,1,21,35,34,7,6,21,17,20,7,6,35,34,38,39,53,30,1,51,50,54,61,2,14,1,35,34,2,17,52,18,51,19,17,35,34,6,16,22,51,50,54,2,237,72,72,134,49,26,58,29,28,104,104,206,62,134,67,79,130,54,120,110,35, +123,88,174,208,208,174,247,214,109,115,115,110,103,110,4,94,32,195,105,106,156,62,62,126,251,202,251,131,130,28,27,182,46,44,162,176,8,125,94,92,1,58,1,7,233,1,60,253,219,1,167,216,254,98,217,218,0,0,0,2,0,157,254,72,4,52,4,94,0,9,0,36,0,0,1,17,33,34, +6,16,22,51,50,54,19,20,2,35,34,38,39,53,30,1,51,50,54,61,2,14,1,35,34,2,17,52,55,54,51,33,3,124,254,248,135,142,143,136,127,135,184,238,231,76,166,83,98,160,67,149,136,44,152,109,196,234,117,113,200,1,233,2,57,1,167,216,254,98,217,218,254,221,252,254, +252,28,27,182,46,44,162,176,8,125,94,92,1,58,1,7,225,165,159,0,0,1,0,122,0,0,4,88,4,152,0,32,0,0,37,17,35,53,33,17,6,7,6,35,34,0,17,16,0,33,50,23,22,23,21,38,39,38,35,34,7,6,16,23,22,51,50,3,178,156,1,66,72,88,78,202,252,254,214,1,44,1,6,62,104,104,128, +120,112,86,72,178,100,98,98,100,178,174,178,1,26,140,253,240,34,20,18,1,62,1,14,1,18,1,58,18,17,75,172,77,27,22,114,113,254,102,113,114,0,2,0,102,254,81,4,107,4,94,0,18,0,27,0,0,1,0,17,20,14,2,34,46,2,53,16,9,1,51,9,1,51,0,50,54,53,16,3,2,17,20,2,226, +1,28,43,93,159,220,158,94,43,1,32,254,114,218,1,46,1,36,216,253,135,227,97,203,219,2,60,254,84,254,179,56,86,65,34,34,65,86,56,1,84,1,172,2,27,254,114,1,142,250,150,76,69,1,34,1,29,254,208,254,241,69,0,0,0,2,0,102,0,0,4,106,4,94,0,12,0,20,0,0,1,22,16, +33,32,53,52,55,1,51,9,1,51,1,6,21,20,51,50,53,52,2,214,178,254,227,254,209,184,254,114,218,1,40,1,42,216,253,246,117,123,113,2,63,241,254,178,167,177,242,2,20,254,115,1,141,253,90,158,59,104,104,63,0,0,1,0,188,254,82,4,21,4,94,0,19,0,0,19,17,51,17,20, +22,51,50,54,53,17,51,17,35,17,14,1,35,34,38,188,184,108,112,130,138,184,184,50,168,114,172,168,1,168,2,182,253,74,151,142,183,171,2,121,249,244,2,86,97,100,225,0,0,0,1,0,195,0,0,4,27,6,20,0,30,0,0,1,7,62,1,51,50,22,21,17,35,17,52,38,35,34,6,21,17,35, +17,53,52,55,54,59,1,21,35,34,6,21,1,125,2,50,168,114,172,168,184,106,114,128,140,184,90,90,164,206,186,90,88,3,194,10,96,99,225,228,253,74,2,182,151,142,183,171,253,135,3,234,148,195,105,106,156,124,126,0,1,0,195,254,86,4,27,6,20,0,40,0,0,1,7,62,1,51, +50,22,21,17,20,7,6,43,1,53,51,50,55,54,53,17,52,38,35,34,6,21,17,35,17,53,52,55,54,59,1,21,35,34,6,21,1,125,2,49,169,114,171,169,88,91,165,204,184,91,45,44,106,114,128,140,184,90,90,164,206,186,90,88,3,194,10,96,99,225,228,253,54,195,105,106,156,62,62, +126,2,202,151,142,183,171,253,135,3,234,148,195,105,106,156,124,126,0,2,0,142,0,0,4,50,6,20,0,3,0,21,0,0,1,51,21,35,5,33,17,33,21,33,17,33,21,33,53,33,17,33,53,33,17,33,2,12,184,184,254,226,1,214,1,98,254,158,1,110,252,110,1,108,254,130,1,126,254,226, +6,20,233,205,254,10,164,254,203,143,143,1,53,164,1,105,0,0,0,1,0,198,0,0,4,10,4,94,0,14,0,0,33,35,34,39,38,53,17,33,53,33,17,20,22,59,1,4,10,204,166,90,88,254,224,1,216,88,90,186,106,102,198,2,59,141,253,56,126,124,0,1,0,160,0,0,4,50,4,94,0,11,0,0,19, +33,21,33,17,33,21,33,53,33,17,33,160,3,146,254,146,1,110,252,110,1,108,254,148,4,94,141,252,190,143,143,3,66,0,1,0,88,0,0,4,121,6,31,0,38,0,0,1,20,23,22,59,1,21,35,34,38,61,1,38,35,34,6,7,53,62,1,51,50,23,17,33,53,33,17,22,51,50,54,55,21,14,1,35,34,39, +2,146,46,72,62,216,234,164,182,46,47,79,141,73,78,146,83,41,38,254,218,1,222,114,92,70,137,74,75,143,79,85,105,1,150,147,40,63,156,212,194,198,10,59,63,174,60,54,6,2,137,144,252,167,53,61,62,174,59,55,45,0,0,0,2,0,157,0,0,4,52,6,31,0,25,0,32,0,0,1,20, +22,59,1,21,35,34,38,61,1,35,32,53,52,51,50,23,17,33,53,33,17,51,21,35,39,38,35,34,21,20,51,2,170,91,89,214,232,165,181,62,254,233,246,53,42,254,217,1,223,250,250,184,23,71,78,92,1,150,124,126,156,212,194,220,189,246,25,1,131,144,252,243,160,160,132,75, +57,0,0,1,0,160,254,86,4,10,6,31,0,13,0,0,5,20,22,59,1,21,35,34,38,53,17,33,53,33,2,127,91,89,215,233,165,181,254,217,1,223,20,124,126,156,212,194,5,163,144,0,0,0,0,1,0,40,254,76,4,168,6,31,0,45,0,0,1,20,22,59,1,21,35,34,38,53,17,35,53,33,17,33,21,1,50, +23,22,23,22,21,20,6,35,34,39,38,39,53,30,1,51,50,54,53,52,39,38,43,1,53,1,33,1,168,72,72,172,187,132,145,236,1,128,2,186,254,183,84,103,79,69,64,243,224,75,79,80,85,67,160,87,152,160,74,74,132,140,1,88,253,236,1,150,124,126,156,212,194,3,249,144,254, +65,168,254,36,56,43,108,104,138,221,242,18,19,37,195,49,50,150,143,132,75,74,166,1,243,0,0,1,0,104,255,227,4,106,4,94,0,33,0,0,37,14,1,35,34,38,25,1,51,17,20,22,51,50,54,53,17,51,17,20,22,50,54,53,17,51,17,35,53,14,1,35,34,38,2,50,34,104,74,136,110,168, +52,70,80,60,168,56,148,56,168,168,32,100,62,76,102,112,72,69,209,1,33,2,137,253,127,237,115,123,229,2,129,253,127,240,112,123,229,2,129,251,160,96,60,63,70,0,0,0,0,1,0,104,254,53,4,106,4,94,0,33,0,0,37,14,1,35,34,38,25,1,51,17,20,22,51,50,54,53,17,51, +17,20,22,50,54,53,17,51,17,35,17,14,1,35,34,38,2,50,34,104,74,136,110,168,52,70,80,60,168,56,148,56,168,168,32,100,62,76,102,112,72,69,209,1,33,2,137,253,127,237,115,123,229,2,129,253,127,240,112,123,229,2,129,249,215,2,41,60,63,70,0,0,0,1,0,103,254, +86,4,105,4,123,0,43,0,0,1,62,1,51,50,22,25,1,20,6,43,1,53,51,50,54,53,17,52,38,35,34,6,21,17,35,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,23,22,2,158,34,105,74,135,111,161,150,186,168,83,78,53,70,80,59,168,57,74,73,57,167,167,33,99,63,83,44,53,3, +238,72,69,209,254,223,253,99,194,212,156,124,126,2,149,237,115,123,229,253,127,2,129,240,112,123,229,253,127,4,94,94,64,59,35,43,0,0,0,0,1,0,178,254,86,4,77,4,123,0,31,0,0,5,20,6,43,1,53,51,50,55,54,53,17,51,21,54,55,54,51,50,23,22,21,17,35,17,52,38, +35,34,7,6,21,1,234,123,136,53,2,68,28,28,186,49,68,67,87,168,86,86,185,92,94,111,65,64,20,214,192,156,48,49,153,4,114,172,101,50,50,119,120,232,253,92,2,158,159,158,95,95,164,0,0,0,1,0,136,254,86,4,30,4,123,0,32,0,0,5,17,52,39,38,35,34,7,6,21,17,35,17, +51,21,62,1,51,50,23,22,21,17,20,23,22,59,1,21,35,34,39,38,2,232,46,47,93,112,64,65,181,181,50,134,88,168,86,86,29,29,63,4,52,136,60,62,20,2,178,159,79,79,95,95,164,253,135,4,94,172,101,100,119,120,232,253,72,153,49,48,156,96,96,0,0,0,1,0,144,0,0,4,65, +4,123,0,9,0,0,19,33,1,17,51,17,33,1,17,35,144,1,16,1,221,196,254,240,254,35,196,4,123,252,121,3,135,251,133,3,135,252,121,0,0,3,0,137,255,227,4,72,4,123,0,10,0,19,0,28,0,0,0,32,18,17,16,2,35,34,2,17,16,37,34,7,6,7,33,38,39,38,19,33,22,23,22,51,50,55, +54,1,127,1,210,247,246,234,233,246,1,223,140,72,63,8,2,55,8,63,72,138,253,211,14,52,72,140,141,72,52,4,123,254,210,254,226,254,225,254,211,1,45,1,31,1,30,146,109,95,176,176,95,109,253,224,132,79,109,109,79,0,0,2,0,69,0,0,4,140,4,96,0,18,0,29,0,0,1,21, +33,17,33,21,33,17,33,21,33,34,39,38,17,16,55,54,51,23,35,34,7,6,21,20,23,22,59,1,4,129,254,139,1,100,254,156,1,128,253,168,243,126,126,126,126,243,32,23,151,75,75,75,75,151,23,4,96,170,254,237,155,254,164,172,142,143,1,20,1,18,142,143,147,104,103,207, +208,104,105,0,0,0,0,2,0,170,255,226,4,38,4,123,0,22,0,46,0,0,1,52,39,38,35,34,7,6,21,16,51,50,55,54,61,1,51,21,20,23,22,51,50,19,20,7,6,35,34,39,38,39,6,7,6,35,34,39,38,53,16,55,18,33,50,23,22,3,128,57,80,145,131,72,74,124,34,41,22,117,23,41,32,125,166, +48,55,137,95,67,27,16,16,27,67,95,118,68,56,64,106,1,21,235,120,90,1,254,156,113,161,111,115,231,254,200,79,43,185,182,182,185,43,79,1,8,171,136,158,122,50,101,101,50,122,154,124,183,0,255,173,1,32,237,176,0,0,0,0,3,0,137,254,86,4,72,6,19,0,29,0,38,0, +47,0,0,1,35,53,33,21,35,21,22,23,22,17,16,7,6,7,21,51,21,33,53,51,53,38,39,38,17,16,55,54,55,23,17,54,55,54,53,52,39,38,3,17,6,7,6,21,20,23,22,2,20,240,2,152,240,161,95,124,123,95,162,240,253,104,240,172,100,123,123,100,172,184,69,44,72,72,44,253,79, +49,72,72,49,5,111,164,164,252,26,117,151,254,226,254,225,150,117,26,240,165,165,237,23,123,150,1,31,1,30,151,123,23,168,252,194,26,66,110,213,214,109,66,252,215,3,72,24,73,109,214,213,110,73,0,0,0,1,0,152,255,229,3,177,4,94,0,17,0,0,55,30,1,51,50,54, +53,17,51,17,35,53,14,1,35,34,38,39,152,59,122,73,172,182,185,185,46,191,131,68,118,54,231,46,42,216,204,2,43,251,162,219,119,127,34,36,0,1,0,152,255,229,3,177,6,31,0,17,0,0,55,30,1,51,50,54,53,17,51,17,35,53,14,1,35,34,38,39,152,59,122,73,172,182,185, +185,46,191,131,68,118,54,231,46,42,216,204,3,236,249,225,219,119,127,34,36,0,1,0,102,254,86,4,128,4,94,0,25,0,0,5,20,22,59,1,21,35,34,38,61,1,14,1,35,34,38,39,53,30,1,51,50,54,53,17,51,3,127,89,90,78,98,165,179,46,191,131,68,118,54,59,122,73,172,182, +185,20,125,125,156,211,195,239,119,127,34,36,188,46,42,216,204,2,43,0,0,0,1,1,106,254,86,4,131,4,123,0,17,0,0,1,46,1,35,34,6,21,17,35,17,51,21,62,1,51,50,22,23,4,131,59,122,73,172,182,185,185,46,191,131,68,118,54,3,121,46,42,216,204,252,41,6,8,217,119, +127,34,36,0,0,0,1,1,106,254,86,4,131,4,123,0,27,0,0,5,20,23,22,59,1,21,35,34,38,53,17,51,21,62,1,51,50,22,23,21,46,1,35,34,7,6,21,2,35,44,44,91,234,254,165,179,185,46,191,131,68,118,54,59,122,73,172,91,91,20,125,63,62,156,211,195,4,114,217,119,127,34, +36,188,46,42,108,108,204,0,1,0,160,0,0,4,50,4,123,0,17,0,0,1,52,55,54,59,1,21,35,34,7,6,21,17,33,21,33,53,33,2,8,82,82,180,210,188,106,38,36,1,112,252,110,1,104,2,229,212,98,96,156,48,50,152,253,170,143,143,0,0,0,0,1,0,160,0,0,4,50,4,123,0,16,0,0,1,17, +33,21,33,53,33,17,52,38,43,1,53,51,50,23,22,2,200,1,106,252,110,1,110,72,108,186,208,180,82,82,2,229,253,170,143,143,2,86,154,96,156,96,98,0,0,2,0,122,0,0,4,87,4,94,0,22,0,33,0,0,1,22,23,22,23,19,35,3,38,39,38,43,1,17,35,17,33,50,23,22,21,20,6,1,17,51, +50,55,54,53,52,39,38,35,2,212,55,53,52,53,174,195,162,63,59,59,97,169,185,1,132,217,108,107,112,253,245,198,119,63,64,64,63,119,2,13,17,54,54,94,254,206,1,31,113,36,37,254,39,4,94,78,77,166,105,140,1,157,254,175,43,43,83,84,42,42,0,2,0,122,0,0,4,87,4, +94,0,22,0,33,0,0,1,30,1,21,20,7,6,35,33,17,51,17,51,50,55,54,55,19,51,3,6,7,6,1,51,50,55,54,53,52,39,38,43,1,2,212,106,112,107,108,217,254,124,185,169,97,59,59,63,162,195,174,53,52,53,254,40,198,119,63,64,64,63,119,198,2,83,27,140,105,162,81,80,4,94, +254,41,37,36,113,1,29,254,208,94,54,54,254,55,42,42,84,83,43,43,0,0,1,0,188,254,86,4,20,4,123,0,56,0,0,1,21,46,1,35,34,7,6,21,20,23,22,31,1,22,23,22,21,20,7,6,35,34,39,20,23,22,59,1,21,35,34,38,61,1,22,23,22,51,50,55,54,53,52,39,38,47,1,38,39,38,53,52, +54,51,50,22,3,216,78,167,91,136,68,70,50,48,148,64,196,82,82,122,124,216,104,106,38,34,110,232,254,180,164,102,100,98,98,130,70,70,50,52,170,64,172,76,76,224,206,102,181,4,63,174,40,40,42,42,84,64,37,36,33,14,42,77,76,137,157,90,91,21,159,55,48,156,192, +214,251,53,26,27,45,44,81,75,40,40,37,15,36,74,75,130,158,172,30,0,0,0,1,0,125,254,86,4,84,6,20,0,19,0,0,5,20,6,43,1,53,51,50,54,53,17,52,54,59,1,21,35,34,6,21,2,211,179,165,254,234,90,90,169,179,221,209,99,77,20,195,211,156,125,125,4,194,184,174,153, +81,103,0,0,0,0,1,0,125,254,86,4,84,6,20,0,31,0,0,1,21,33,17,20,6,43,1,53,51,50,54,53,17,33,53,33,17,33,53,33,53,52,54,59,1,21,35,34,6,21,17,4,52,254,159,179,165,254,234,90,90,254,129,1,127,254,195,1,61,169,179,221,209,99,77,2,104,164,254,40,195,211,156, +125,125,1,216,164,1,105,141,80,184,174,153,81,103,253,165,0,0,0,1,0,125,254,86,4,84,4,94,0,21,0,0,1,17,20,23,22,59,1,21,35,34,38,53,17,52,39,38,43,1,53,51,50,22,2,211,39,38,99,209,221,179,169,45,45,90,234,254,165,179,2,200,252,223,103,40,41,153,174,184, +3,12,124,64,62,156,211,0,0,0,0,2,0,118,254,86,4,91,6,20,0,8,0,33,0,0,5,35,34,21,20,51,50,55,54,55,51,21,35,6,7,6,35,32,53,52,33,51,17,52,55,54,59,1,21,35,34,7,6,21,2,56,179,116,127,110,33,18,202,183,191,18,53,82,181,254,209,1,14,190,87,81,195,174,176, +100,37,39,154,51,65,48,23,199,155,111,64,96,216,210,4,174,180,92,86,153,40,41,103,0,0,1,0,166,254,194,4,43,4,96,0,19,0,0,1,17,33,53,33,17,52,38,43,1,53,51,50,22,21,17,33,21,33,17,2,72,254,94,1,162,94,117,207,225,207,170,1,43,254,213,254,194,1,62,143, +2,96,124,98,147,166,203,253,160,143,254,194,0,0,1,0,131,254,87,4,8,5,158,0,19,0,0,1,17,33,21,33,17,20,22,59,1,21,35,34,38,53,17,33,53,33,17,2,102,1,162,254,94,94,117,207,225,207,170,254,213,1,43,5,158,254,194,143,251,247,124,98,147,166,203,4,9,143,1, +62,0,0,2,0,0,255,227,4,209,4,96,0,23,0,33,0,0,17,53,51,17,51,17,33,17,51,17,51,21,35,17,35,53,6,7,6,35,34,38,61,1,41,1,21,20,23,22,51,50,55,54,142,184,2,58,184,153,153,184,67,89,89,117,193,199,2,241,253,199,62,62,124,149,87,77,1,196,164,1,248,254,8,1, +248,254,8,164,254,60,172,102,50,49,240,231,10,3,159,80,79,95,85,0,0,0,0,1,0,95,255,226,4,114,4,96,0,35,0,0,19,53,33,21,6,7,6,21,20,22,32,55,54,53,52,39,38,39,53,33,21,35,22,23,22,21,20,0,32,39,38,53,52,55,54,55,95,1,186,109,63,66,176,1,32,88,88,66,71, +100,1,180,236,114,56,54,254,228,254,62,142,142,52,53,119,3,188,164,220,69,105,111,135,159,194,97,98,158,146,100,111,63,220,164,100,113,110,136,235,254,220,145,146,228,147,107,109,104,0,1,0,65,0,0,4,119,4,96,0,32,0,0,1,33,22,23,22,21,20,0,43,1,34,39,38, +53,17,35,53,33,17,20,23,22,63,1,50,55,54,53,52,39,38,39,38,2,85,1,66,114,56,54,254,228,225,70,181,82,81,155,1,83,38,40,103,51,144,88,88,66,79,92,76,3,218,100,113,110,136,235,254,220,96,96,214,2,59,143,253,54,153,49,50,2,1,97,98,158,146,100,119,55,44, +0,0,0,0,1,0,72,0,0,4,138,4,96,0,6,0,0,33,35,9,1,35,1,51,4,138,196,254,162,254,162,194,1,164,250,3,172,252,84,4,96,0,0,0,1,0,15,0,0,4,194,4,96,0,12,0,0,33,35,11,1,35,11,1,35,19,51,27,1,51,4,194,148,184,183,173,184,184,147,235,173,193,194,173,3,106,252, +150,3,106,252,150,4,96,252,106,3,150,0,0,1,0,72,0,0,4,138,6,10,0,15,0,0,1,62,1,59,1,21,35,34,6,15,1,1,35,9,1,35,2,52,78,148,124,146,108,76,84,50,34,1,198,196,254,162,254,162,194,4,200,200,122,154,72,134,84,251,178,3,108,252,148,0,0,1,0,102,0,0,4,107, +4,125,0,8,0,0,19,51,9,1,51,1,17,35,17,102,217,1,37,1,46,217,254,93,203,4,125,254,56,1,200,253,144,253,243,2,13,0,0,0,0,1,0,194,254,86,4,15,4,96,0,20,0,0,19,33,21,1,33,23,20,23,22,59,1,21,35,34,38,61,1,33,53,1,33,213,2,167,253,249,2,25,1,21,21,59,27,52, +136,122,253,233,2,7,254,12,4,96,168,252,219,167,153,49,48,156,192,214,20,168,3,37,0,2,0,167,255,145,4,42,4,96,0,20,0,27,0,0,33,6,21,35,52,55,33,53,1,33,53,33,21,1,51,18,51,50,23,22,33,39,51,50,53,52,35,6,2,170,3,153,3,254,150,2,180,253,101,3,106,253, +76,175,60,219,227,1,1,254,178,20,20,174,70,88,51,60,59,52,168,3,37,147,168,252,219,1,32,246,189,147,54,91,2,0,0,1,0,125,254,76,4,84,4,96,0,32,0,0,1,50,23,22,23,22,21,20,4,33,34,39,38,39,53,30,1,51,50,55,54,53,52,39,38,43,1,53,1,33,53,33,21,2,97,106,128, +98,86,81,254,208,254,232,94,99,100,106,84,200,109,190,99,100,92,93,165,174,1,174,253,101,3,106,1,220,56,42,109,104,138,221,242,18,19,37,195,49,50,75,75,143,132,75,74,166,1,243,147,168,0,2,0,105,254,76,4,104,4,96,0,36,0,45,0,0,1,32,55,54,5,22,23,54,53, +52,39,38,43,1,53,1,33,53,33,21,1,50,23,22,23,22,21,20,7,22,21,35,52,39,48,7,6,55,38,35,34,7,20,51,50,55,1,227,254,177,2,2,1,42,246,158,12,92,94,164,174,1,174,253,101,3,106,254,101,105,129,100,84,81,39,100,153,40,20,151,9,125,197,131,1,158,190,99,254, +76,189,251,5,4,59,42,49,133,74,74,166,1,243,147,168,254,36,56,43,108,103,139,113,85,101,164,82,56,17,121,250,42,75,47,75,0,0,0,0,1,0,194,0,0,4,15,6,18,0,28,0,0,1,51,50,55,54,53,52,39,38,35,34,7,6,7,53,54,55,54,51,32,23,22,21,20,7,6,7,17,35,1,190,63,191, +87,58,58,102,176,80,79,78,78,76,81,81,85,1,19,138,109,108,112,170,203,3,30,114,76,98,133,65,114,22,21,43,172,35,17,18,157,125,186,170,115,119,30,253,116,0,1,0,194,0,0,4,15,6,18,0,28,0,0,1,17,35,17,38,39,38,53,52,55,54,33,50,23,22,23,21,38,39,38,35,34, +7,6,7,20,23,22,51,3,18,202,170,112,108,110,137,1,19,85,81,81,76,78,79,78,80,179,99,57,1,58,86,192,3,30,252,226,2,140,30,119,115,170,186,125,157,18,17,35,172,43,21,22,114,65,133,98,76,114,0,0,0,1,0,194,0,0,4,15,6,18,0,28,0,0,1,17,51,17,22,23,22,21,20, +7,6,33,34,39,38,39,53,22,23,22,51,50,55,54,55,52,39,38,35,1,190,203,170,112,108,109,138,254,237,85,81,81,76,78,78,79,80,179,99,57,1,58,86,192,2,244,3,30,253,116,30,119,115,170,186,125,157,18,17,35,172,43,21,22,114,65,133,98,76,114,0,0,0,1,0,194,254,74, +4,15,6,18,0,35,0,0,19,52,55,54,33,50,23,22,23,21,38,39,38,35,34,7,6,7,17,22,23,22,51,50,55,54,55,21,6,7,6,35,32,39,38,53,194,110,137,1,19,85,81,81,76,78,79,78,80,179,99,57,1,1,57,99,179,80,78,79,78,76,81,81,85,254,237,137,110,4,62,186,125,157,18,17,35, +172,43,21,22,114,65,133,251,224,133,65,114,22,21,43,172,35,17,18,157,125,186,0,0,0,0,3,0,95,0,45,4,115,4,66,0,12,0,26,0,40,0,0,19,52,55,54,51,50,23,22,21,20,0,32,0,55,20,23,22,32,54,53,52,39,38,35,34,7,6,23,52,55,54,51,50,23,22,21,20,6,34,39,38,95,154, +154,216,212,154,154,254,209,254,79,254,204,181,101,100,1,26,198,100,101,138,141,100,101,227,34,33,47,46,34,33,66,94,33,34,2,53,212,156,157,157,156,212,216,254,208,1,48,217,141,99,99,198,141,138,102,102,102,102,137,46,34,34,34,34,46,47,66,33,33,0,0,0, +3,0,209,0,0,4,0,4,125,0,8,0,17,0,32,0,45,64,24,25,0,182,10,32,9,182,18,194,1,182,32,14,18,22,5,18,28,0,9,6,18,70,33,16,252,236,50,212,236,212,236,49,0,47,236,244,236,16,212,236,57,48,1,17,51,50,54,53,52,38,35,3,17,51,50,54,53,52,38,35,37,33,50,22,21, +20,6,7,30,1,21,20,6,35,33,1,155,221,93,95,90,94,225,210,85,84,84,86,254,101,1,141,178,192,98,96,115,127,209,193,254,99,2,18,254,152,105,63,92,100,1,194,254,232,85,63,46,86,169,148,136,105,125,15,25,156,117,154,168,0,0,0,2,0,176,255,214,4,34,4,121,0,21, +0,43,0,0,1,34,7,6,20,23,22,59,1,21,35,34,7,6,21,20,23,22,51,36,17,16,39,4,17,16,5,6,39,34,39,38,53,52,54,55,46,1,53,52,55,54,51,50,2,50,115,57,64,60,32,138,137,137,138,32,60,64,55,117,1,84,120,1,20,254,236,86,147,173,100,100,106,98,98,106,100,100,173, +150,3,216,54,61,154,55,30,157,30,54,78,74,64,54,1,1,190,1,162,115,151,254,120,254,168,194,62,2,87,86,148,103,142,28,27,142,103,148,87,86,0,1,0,54,0,0,4,108,6,18,0,48,0,0,37,17,35,53,33,17,6,7,6,35,34,39,38,17,16,55,54,51,50,23,22,23,53,52,55,54,59,1, +21,35,34,7,6,29,1,35,21,38,39,38,35,34,7,6,16,23,22,51,50,2,206,116,1,30,1,163,58,152,212,123,125,127,124,219,51,72,24,13,62,60,136,190,129,78,30,28,2,29,189,63,55,134,75,74,74,75,134,130,178,1,26,140,253,240,4,50,18,159,160,1,13,1,15,160,157,18,6,5, +1,216,94,96,156,48,51,151,148,106,38,66,22,114,113,254,102,113,114,0,0,0,0,1,0,144,0,0,4,65,4,123,0,11,0,0,19,51,17,33,17,51,17,35,17,33,17,35,144,202,2,29,202,202,253,227,202,4,123,254,65,1,191,251,133,2,18,253,238,0,0,3,0,202,254,86,4,7,6,20,0,3,0, +20,0,29,0,0,1,51,21,35,23,17,51,21,35,6,7,6,35,32,53,52,33,51,17,33,53,1,35,34,23,22,51,50,55,54,2,154,184,184,184,180,190,19,53,81,181,254,208,1,14,194,254,194,1,51,181,119,3,3,123,106,38,17,6,20,233,203,251,160,155,112,63,96,221,205,3,209,143,251,6, +51,65,48,23,0,0,0,0,1,0,119,254,76,4,90,4,96,0,10,0,0,1,35,17,1,35,9,1,51,1,17,51,4,90,186,253,220,236,2,82,253,150,240,2,56,186,254,76,3,151,254,29,2,12,2,84,253,221,2,35,0,0,0,0,1,0,245,0,0,3,220,4,123,0,5,0,0,19,51,17,33,21,33,245,202,2,29,253,25, +4,123,252,47,170,0,0,2,0,35,254,86,4,124,6,18,0,29,0,41,0,0,37,6,7,6,35,34,39,38,16,55,54,51,50,23,22,23,53,52,55,54,59,1,21,35,34,7,6,21,17,35,0,16,23,22,50,55,54,16,39,38,34,7,2,187,44,66,67,93,174,110,109,109,110,174,93,67,66,44,61,61,136,190,127, +79,29,28,185,254,41,63,63,219,63,63,63,63,219,63,168,100,48,49,162,162,2,16,162,162,49,48,100,198,214,96,96,156,48,49,153,249,218,4,164,254,106,116,115,115,116,1,150,116,115,115,0,0,0,1,0,194,0,0,4,15,6,18,0,36,0,0,1,51,50,55,54,53,52,39,38,35,34,7,6, +7,53,54,55,54,51,32,23,22,21,20,7,6,7,21,51,21,35,17,35,17,35,53,51,1,190,63,191,87,58,58,102,176,80,79,78,78,76,81,81,85,1,19,138,109,108,112,170,231,231,202,229,228,3,30,114,76,98,133,65,114,22,21,43,172,35,17,18,157,125,186,170,115,119,30,212,164, +254,236,1,20,164,0,0,0,0,1,0,194,0,0,4,15,6,18,0,36,0,0,1,53,38,39,38,53,52,55,54,33,50,23,22,23,21,38,39,38,35,34,7,6,21,20,23,22,59,1,17,51,21,35,17,35,17,35,53,2,72,170,112,108,110,137,1,19,85,81,81,76,78,79,78,80,176,102,58,58,87,191,62,229,229,202, +231,1,184,212,30,119,115,170,186,125,157,18,17,35,172,43,21,22,114,65,133,98,76,114,254,154,164,254,236,1,20,164,0,0,0,3,0,29,255,227,4,154,6,20,0,7,0,32,0,35,0,0,18,16,22,50,54,16,38,34,5,17,51,17,33,21,1,33,21,33,43,1,53,6,7,6,35,34,2,16,18,51,50,23, +22,23,17,1,168,100,175,101,101,175,1,20,110,2,11,254,97,1,159,253,245,16,94,33,59,56,78,128,161,161,128,78,56,58,144,1,143,2,250,254,106,231,231,1,150,231,43,2,94,254,76,168,252,219,147,168,97,51,49,1,68,2,16,1,68,49,48,77,252,251,3,5,0,0,0,2,0,27,254, +76,4,180,6,20,0,13,0,67,0,0,18,16,23,22,51,50,55,54,16,39,38,35,34,7,37,19,35,53,6,7,6,35,34,39,38,16,55,54,51,50,23,22,23,17,51,3,33,21,3,50,23,22,23,22,21,20,6,35,34,39,38,39,53,30,1,51,50,55,54,53,52,39,38,43,1,53,1,33,141,50,50,88,87,51,50,50,51, +87,88,50,1,180,1,111,35,53,53,74,122,76,77,77,76,122,74,53,53,35,111,1,2,12,246,63,77,59,51,49,182,168,57,59,60,64,51,120,65,114,59,60,55,56,99,104,1,2,254,113,2,250,254,106,116,115,115,116,1,150,116,115,115,95,252,51,168,100,48,49,162,162,2,16,162,162, +49,48,100,2,94,254,76,168,254,36,56,42,109,104,138,221,242,18,19,37,195,49,50,75,75,143,132,75,74,166,1,243,0,0,0,4,0,54,255,145,4,153,6,20,0,7,0,11,0,44,0,51,0,0,18,16,22,50,54,16,38,34,5,19,1,33,53,33,21,1,51,18,51,50,21,22,43,1,6,21,35,52,55,39,35, +53,14,1,35,34,2,16,18,51,50,22,23,17,51,1,51,50,53,52,35,6,169,100,175,101,101,175,1,127,3,1,141,254,115,2,9,254,97,105,36,132,136,1,200,25,2,92,1,216,92,35,106,75,121,153,153,121,75,106,35,110,1,48,12,104,42,53,2,250,254,106,231,231,1,150,231,20,252, +254,3,2,147,168,252,219,1,32,246,189,51,60,83,27,1,168,100,97,1,68,2,16,1,68,97,100,2,94,250,127,54,91,2,0,0,1,0,153,255,227,4,56,5,158,0,62,0,0,1,21,46,1,35,34,6,21,20,22,31,1,22,23,22,21,20,6,35,34,39,38,39,21,35,34,38,53,17,35,53,51,17,51,17,51,21, +35,17,20,22,59,1,53,30,1,51,50,54,53,52,39,38,47,1,46,1,53,52,54,51,50,22,4,20,47,101,54,82,82,59,89,37,119,48,50,148,130,54,58,56,62,113,128,97,81,81,111,227,227,45,69,107,62,118,59,78,84,31,27,106,38,103,91,135,123,61,108,4,63,174,40,40,84,84,64,73, +33,14,44,75,76,137,156,182,17,17,33,38,159,210,2,96,143,1,62,254,194,143,253,160,137,78,77,53,53,89,81,75,40,36,41,15,36,149,130,158,172,30,0,0,0,0,2,0,153,254,86,4,52,6,20,0,37,0,46,0,0,1,17,33,53,52,55,54,59,1,21,35,34,7,6,21,19,20,7,6,43,1,53,51,50, +55,54,61,1,35,34,39,38,53,17,35,53,51,17,1,2,17,33,17,20,23,22,51,1,137,1,25,65,60,147,130,132,74,28,30,2,61,61,136,53,37,78,29,29,141,161,59,61,101,101,1,165,1,254,231,28,29,85,5,158,254,194,78,182,90,86,153,40,41,103,251,41,215,95,96,156,48,50,152, +20,80,77,212,2,96,143,1,62,250,252,1,23,2,32,253,160,138,38,39,0,0,3,0,181,255,112,4,18,5,158,0,46,0,54,0,64,0,0,1,17,51,21,54,51,50,23,22,23,21,38,39,38,35,34,7,6,16,23,22,23,54,51,50,23,20,35,34,39,6,21,7,52,55,38,39,21,35,34,38,53,17,35,53,51,17,1, +22,51,50,53,52,35,34,7,38,53,16,55,35,17,20,22,51,1,117,228,90,157,51,49,48,46,47,47,47,48,108,59,59,59,4,4,50,118,179,1,200,49,43,3,92,7,33,28,114,128,97,81,81,1,254,36,45,87,79,61,213,77,84,221,45,69,5,158,254,194,130,157,17,18,35,172,43,22,21,113, +114,254,102,114,7,7,176,246,189,17,57,68,3,104,84,34,50,128,159,210,2,96,143,1,62,250,244,19,57,75,105,157,248,1,7,155,253,160,137,78,0,0,0,1,0,135,254,86,4,72,6,20,0,51,0,0,1,17,20,7,6,43,1,53,51,50,55,54,53,17,52,38,35,34,6,21,17,35,17,35,17,35,17, +35,53,51,53,52,54,59,1,21,35,34,6,29,1,59,2,21,54,55,54,51,50,23,22,4,71,49,49,108,153,140,63,23,23,75,74,89,104,111,180,110,106,106,104,113,105,106,59,47,180,2,109,40,53,54,70,116,60,59,2,164,253,72,214,96,96,156,48,49,153,2,178,159,158,190,164,253, +135,3,209,252,47,3,209,143,78,187,171,153,80,104,99,174,101,50,50,119,120,0,0,2,0,230,255,227,3,235,6,20,0,37,0,55,0,0,1,21,38,39,38,35,34,6,21,20,23,22,31,1,22,23,22,21,20,7,6,35,34,39,38,39,21,35,17,51,17,54,55,54,51,50,23,22,1,17,22,23,22,51,50,55, +54,53,52,39,38,47,1,38,39,38,3,190,59,62,65,66,103,102,36,38,110,47,149,60,62,93,91,163,65,76,79,68,138,138,8,75,84,155,76,68,67,253,235,75,69,74,73,97,53,52,37,34,133,48,128,57,50,4,63,174,41,19,20,84,84,63,38,36,33,14,44,75,76,137,155,92,91,17,21,29, +38,6,20,253,58,138,77,86,15,15,254,183,253,206,51,23,27,45,43,82,75,40,35,42,15,36,74,65,0,0,0,2,0,219,0,0,3,244,6,20,0,10,0,13,0,0,19,51,17,33,21,1,33,21,33,43,1,19,17,1,219,138,2,143,253,249,2,7,253,113,20,118,138,1,243,6,20,254,76,168,252,219,147, +3,205,252,250,3,6,0,0,2,0,143,255,226,4,66,5,32,0,12,0,25,0,0,19,51,27,1,51,27,1,51,3,35,11,1,35,3,51,27,1,51,27,1,51,3,35,11,1,35,143,116,145,144,137,145,144,116,185,136,152,153,136,185,116,145,144,137,145,144,116,185,136,152,153,136,2,85,254,23,1,233, +254,23,1,233,253,141,2,2,253,254,5,61,254,23,1,233,254,23,1,233,253,141,2,2,253,254,0,2,0,143,0,173,4,66,5,31,0,7,0,15,0,0,19,33,17,35,17,33,17,35,17,33,17,35,17,33,17,35,143,3,179,143,253,107,143,3,179,143,253,107,143,2,85,254,88,1,5,254,251,4,114,254, +88,1,5,254,251,0,0,0,0,1,0,178,254,74,4,31,6,20,0,24,0,0,5,32,25,1,52,38,43,1,53,51,50,22,21,17,16,51,50,54,53,17,51,17,35,17,6,2,132,254,219,57,79,37,53,136,122,186,112,129,138,138,99,29,1,215,2,196,153,97,156,192,214,253,66,254,195,190,164,2,121,249, +236,2,98,201,0,0,0,1,0,197,254,86,4,12,6,20,0,34,0,0,1,16,51,50,54,53,17,51,17,6,22,59,1,21,35,34,39,38,39,53,6,35,34,25,1,52,39,38,43,1,53,51,50,22,21,1,190,148,90,103,111,2,48,62,30,42,109,47,50,1,79,138,235,23,23,63,29,42,109,98,1,192,254,195,190, +164,2,121,251,142,148,102,156,92,103,231,172,201,1,215,2,196,153,49,48,156,192,214,0,0,0,1,1,65,2,156,3,144,6,4,0,19,0,32,64,6,0,3,14,10,11,20,16,212,220,60,47,204,75,49,0,64,6,6,17,12,2,11,20,16,212,60,196,212,204,48,1,17,35,17,52,38,35,34,6,21,17,35, +17,51,17,62,1,51,50,22,3,144,116,78,78,94,108,117,117,41,113,74,121,125,4,23,254,133,1,119,89,89,107,92,254,158,3,103,254,171,56,56,134,0,0,1,1,65,2,154,3,144,6,2,0,31,0,0,1,51,62,1,51,50,22,21,17,35,17,52,38,35,34,6,21,17,35,17,53,52,55,54,59,1,21,35, +34,7,6,21,1,181,1,41,113,74,121,125,116,78,78,94,108,117,52,51,114,160,147,66,24,24,4,172,57,56,134,130,254,134,1,119,89,88,106,92,254,158,2,49,83,119,54,54,87,27,28,85,0,0,0,2,1,230,1,173,2,235,6,4,0,11,0,15,0,0,1,51,17,20,6,43,1,53,51,50,54,53,17,51, +21,35,2,119,116,103,114,44,31,66,48,116,116,5,15,253,130,120,108,88,54,86,3,114,130,0,0,1,1,153,2,156,3,56,5,31,0,17,0,0,1,46,1,35,34,6,21,17,35,17,51,21,62,1,51,50,22,23,3,55,19,46,28,98,106,116,116,37,117,84,12,29,18,4,175,10,9,113,107,254,182,2,115, +97,57,55,2,3,0,0,0,1,1,153,2,140,3,56,5,16,0,17,0,0,1,30,1,51,50,54,53,17,51,17,35,53,14,1,35,34,38,39,1,154,19,46,28,98,106,116,116,37,117,84,12,29,18,2,252,10,9,113,107,1,74,253,141,97,57,55,3,2,0,0,0,1,1,81,1,173,3,128,5,16,0,31,0,0,1,30,1,51,50,54, +53,17,51,17,29,1,20,23,22,59,1,21,35,34,39,38,61,1,35,53,14,1,35,34,38,39,1,81,20,46,28,98,105,117,24,24,66,31,45,114,51,51,1,36,118,83,12,29,18,2,252,10,9,113,107,1,74,253,213,72,11,86,27,27,88,54,54,120,11,97,57,55,3,2,0,0,0,2,1,48,2,156,3,161,5,16, +0,22,0,33,0,0,1,30,1,21,20,7,6,43,1,17,51,17,51,50,55,54,63,1,51,7,6,7,6,1,51,50,55,54,53,52,39,38,43,1,2,172,67,71,68,68,137,244,117,106,61,37,37,40,102,123,110,33,33,33,254,215,124,75,40,40,40,40,75,124,3,233,15,78,59,91,45,45,2,115,254,247,21,20,63, +161,171,53,30,30,255,0,23,24,47,46,24,25,0,1,0,143,2,156,4,66,5,16,0,12,0,0,19,51,27,1,51,27,1,51,3,35,11,1,35,143,116,145,144,137,145,144,116,185,136,152,153,136,5,15,254,23,1,233,254,23,1,233,253,141,2,2,253,254,0,1,1,17,1,173,3,192,5,16,0,15,0,0,1, +14,1,43,1,53,51,50,54,63,1,1,51,27,1,51,2,138,49,93,79,92,68,48,53,32,21,254,226,123,220,221,123,2,98,112,69,87,40,75,47,2,105,254,22,1,234,0,0,0,255,255,1,236,4,116,2,235,6,102,16,6,2,203,0,0,255,255,1,207,3,199,3,45,6,20,16,6,7,35,0,0,255,255,1,207, +3,199,3,45,6,20,16,6,7,36,0,0,255,255,1,240,4,194,2,225,6,193,16,6,2,156,0,0,0,1,1,223,3,239,2,242,6,20,0,16,0,0,1,52,53,50,54,53,52,38,35,52,53,50,23,22,20,7,6,1,224,64,88,88,64,114,80,80,80,80,3,239,61,62,88,64,63,88,61,62,80,79,230,80,80,0,0,0,0,1, +1,223,3,239,2,242,6,20,0,16,0,0,1,34,39,38,52,55,54,51,20,21,34,6,21,20,22,51,20,2,242,116,80,78,78,80,116,64,88,88,64,3,239,80,80,230,79,80,62,61,88,63,64,88,62,0,0,0,0,1,1,94,3,142,3,115,6,245,0,28,0,0,1,51,50,55,54,53,52,39,38,35,34,7,6,7,53,54,55, +54,51,50,23,22,21,20,7,6,7,17,35,1,253,40,121,54,36,36,62,113,51,49,50,49,48,51,51,54,173,87,69,68,71,107,127,5,77,64,42,55,75,36,64,12,12,24,96,20,9,10,88,70,104,95,64,67,17,254,147,0,0,1,1,94,3,142,3,115,6,245,0,28,0,0,1,17,35,17,38,39,38,53,52,55, +54,51,50,23,22,23,21,38,39,38,35,34,7,6,21,20,23,22,51,2,211,127,107,71,68,70,86,173,54,51,51,48,49,50,49,51,113,62,36,36,54,121,5,77,254,65,1,109,17,67,64,95,104,70,88,10,9,20,96,24,12,12,64,36,75,55,42,64,0,1,1,41,4,238,3,168,6,102,0,6,0,55,64,12,4, +5,2,186,0,185,7,4,2,11,6,7,16,212,236,57,49,0,16,244,236,50,57,48,0,75,176,9,84,75,176,14,84,91,88,189,0,7,255,192,0,1,0,7,0,7,0,64,56,17,55,56,89,1,51,19,35,39,7,35,2,31,147,246,139,181,180,139,6,102,254,136,245,245,0,0,0,1,1,41,4,238,3,168,6,102,0, +6,0,55,64,12,3,0,186,4,1,185,7,3,5,11,1,7,16,212,236,57,49,0,16,244,60,236,57,48,0,75,176,9,84,75,176,14,84,91,88,189,0,7,255,192,0,1,0,7,0,7,0,64,56,17,55,56,89,1,3,51,23,55,51,3,2,31,246,139,180,181,139,246,4,238,1,120,245,245,254,136,0,1,2,36,3,231, +2,173,6,18,0,3,0,19,64,3,0,3,4,16,212,204,49,0,64,3,3,2,4,16,212,196,48,1,17,35,17,2,172,136,6,18,253,213,2,43,0,0,255,255,1,61,5,98,3,147,5,246,16,6,2,140,0,0,0,1,2,36,254,209,2,173,0,252,0,3,0,19,64,3,0,3,4,16,212,204,49,0,64,3,3,2,4,16,212,196,48, +37,17,35,17,2,172,136,252,253,213,2,43,0,0,0,255,255,1,61,254,155,3,148,255,47,16,6,2,185,0,0,255,255,1,121,253,184,3,88,255,48,16,7,0,67,0,98,248,202,0,0,255,255,1,121,253,184,3,88,255,48,16,7,0,118,255,158,248,202,0,0,0,2,1,182,0,0,3,27,4,35,0,2,0, +5,0,0,1,3,33,3,19,33,2,104,178,1,101,179,179,254,155,2,217,1,74,253,39,254,182,0,0,1,1,182,2,216,3,27,4,35,0,2,0,0,1,3,33,2,104,178,1,101,2,217,1,74,0,0,255,255,1,223,1,254,2,242,4,35,16,7,2,99,0,0,254,15,0,0,255,255,1,223,1,254,2,242,4,35,16,7,2,100, +0,0,254,15,0,0,0,1,1,62,0,255,3,148,3,85,0,11,0,0,1,53,51,21,51,21,35,21,35,53,35,53,2,30,150,224,224,150,224,2,117,224,224,150,224,224,150,0,0,0,0,1,1,136,1,223,3,74,2,117,0,3,0,0,1,33,53,33,3,74,254,62,1,194,1,223,150,0,255,255,1,47,5,41,3,162,6,72, +16,6,2,142,0,0,255,255,2,1,5,68,2,206,6,16,16,6,2,143,0,0,0,2,1,86,4,225,3,123,7,6,0,11,0,23,0,87,178,15,200,9,184,1,4,64,12,21,200,3,24,12,80,0,123,18,80,6,24,16,212,236,244,236,49,0,16,212,236,244,236,48,0,75,176,9,84,75,176,12,84,91,88,189,0,24,255, +192,0,1,0,24,0,24,0,64,56,17,55,56,89,1,75,176,9,84,88,189,0,24,0,64,0,1,0,24,0,24,255,192,56,17,55,56,89,1,20,6,35,34,38,53,52,54,51,50,22,7,52,38,35,34,6,21,20,22,51,50,54,3,123,159,116,115,159,159,115,116,159,123,88,64,64,87,87,64,64,88,5,244,115, +160,160,115,115,159,159,115,63,88,87,64,65,87,88,0,0,1,1,164,254,117,3,25,0,0,0,19,0,34,179,11,14,10,7,184,1,6,64,9,14,0,1,0,10,4,124,17,20,16,212,236,196,212,204,49,0,47,212,252,196,18,57,48,33,51,14,1,21,20,22,51,50,54,55,21,14,1,35,34,38,53,52,54, +2,16,119,45,43,55,54,32,62,31,38,68,30,122,115,53,61,88,31,46,46,15,15,133,10,10,87,93,48,105,0,0,0,1,1,31,5,29,3,178,6,55,0,27,0,187,64,33,0,18,7,14,11,4,1,18,7,15,11,4,18,204,25,7,4,204,21,11,28,15,1,14,0,7,21,80,22,7,80,8,28,16,212,236,212,236,17, +57,57,57,57,49,0,16,212,60,252,212,60,236,17,18,57,17,18,57,17,18,57,17,18,57,48,0,75,176,9,84,75,176,12,84,91,88,189,0,28,255,192,0,1,0,28,0,28,0,64,56,17,55,56,89,0,75,176,15,84,88,189,0,28,0,64,0,1,0,28,0,28,255,192,56,17,55,56,89,64,63,9,0,12,10, +12,11,12,12,11,15,11,16,15,17,15,18,15,19,15,20,15,21,15,22,15,23,9,27,25,0,25,1,27,10,27,11,27,12,27,13,27,14,27,15,27,16,27,17,27,18,27,19,31,20,31,21,31,22,26,23,25,27,31,1,93,1,39,46,1,35,34,6,7,35,62,1,51,50,22,31,1,30,1,51,50,54,55,51,14,1,35,34, +38,2,100,57,21,33,14,38,36,2,124,1,102,91,39,64,37,57,21,33,13,39,36,1,125,1,102,91,39,64,5,90,55,20,19,74,81,134,148,28,33,55,20,19,74,81,134,148,28,0,0,0,255,255,1,88,4,238,4,23,6,102,16,6,2,147,0,0,0,1,254,161,1,222,3,115,4,8,0,15,0,0,1,37,51,21,20, +23,22,59,1,21,33,34,39,38,53,5,254,161,2,107,184,38,38,105,250,254,241,175,87,82,253,150,3,100,164,148,153,49,48,156,96,90,200,162,0,0,0,2,1,37,1,171,3,172,5,15,0,13,0,21,0,0,1,22,21,20,7,4,39,38,55,3,51,23,55,51,1,6,23,22,51,50,53,54,2,181,178,242,254, +246,1,1,182,250,136,191,184,136,254,188,139,3,1,135,128,1,3,220,249,180,129,3,3,135,192,241,1,47,224,224,254,138,174,152,77,77,140,0,0,0,0,1,1,86,2,156,3,124,6,10,0,13,0,0,1,20,22,59,1,21,35,34,38,53,17,35,53,33,2,132,56,56,136,146,104,114,186,1,46,3, +127,69,71,87,119,108,2,58,81,0,0,0,0,1,1,91,2,156,3,118,5,47,0,41,0,0,1,21,46,1,35,34,6,21,20,22,31,1,22,23,22,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,39,38,47,1,46,1,53,52,54,51,50,22,3,80,49,106,56,87,86,62,93,40,125,50,52,155,137,56,123,68,64,125, +61,82,88,32,28,111,41,107,96,141,130,64,113,5,13,97,22,22,47,47,36,41,18,8,24,42,43,77,87,102,20,19,107,30,30,50,45,42,23,20,23,8,21,83,73,88,97,17,0,1,1,18,2,156,3,191,5,15,0,11,0,0,1,3,1,35,39,7,35,1,3,51,23,55,3,177,255,1,13,137,206,205,137,1,18,250, +136,188,187,5,15,254,207,254,190,246,246,1,72,1,43,223,223,0,0,1,1,94,2,156,3,115,6,2,0,28,0,0,1,17,35,17,38,39,38,53,52,55,54,51,50,23,22,23,21,38,39,38,35,34,7,6,21,20,23,22,51,2,211,127,107,71,68,70,86,173,54,51,51,48,49,50,49,51,113,62,36,36,54,121, +4,91,254,65,1,109,17,67,64,95,104,70,88,10,9,20,96,24,12,12,64,36,75,55,42,64,0,1,1,44,0,0,3,165,5,88,0,5,0,0,33,17,33,53,33,17,3,29,254,15,2,121,4,208,136,250,168,0,0,1,1,44,0,0,3,165,5,88,0,7,0,0,33,17,33,53,33,17,51,17,3,29,254,15,1,241,136,3,156, +136,1,52,250,168,0,1,1,44,0,0,3,165,5,88,0,7,0,0,1,17,51,17,35,17,33,53,3,29,136,136,254,15,2,240,2,104,250,168,2,104,136,0,0,0,0,1,1,44,0,0,3,165,5,88,0,7,0,0,1,17,51,17,35,17,33,53,3,29,136,136,254,15,1,188,3,156,250,168,1,52,136,0,0,0,0,1,1,44,0,0, +3,165,5,88,0,5,0,0,37,17,51,17,33,53,3,29,136,253,135,136,4,208,250,168,136,0,255,255,0,211,3,199,3,252,6,20,18,6,7,40,0,0,255,255,1,141,254,10,3,68,255,193,16,6,2,173,0,0,255,255,1,23,4,238,2,246,6,102,16,6,0,67,0,0,255,255,1,219,4,238,3,186,6,102,16, +6,0,118,0,0,255,255,1,41,4,238,3,168,6,102,16,6,2,103,0,0,255,255,1,31,5,29,3,178,6,55,16,6,2,121,0,0,0,1,1,61,5,98,3,147,5,246,0,3,0,17,182,2,182,0,4,1,0,4,16,212,204,49,0,16,212,236,48,1,33,21,33,1,61,2,86,253,170,5,246,148,255,255,0,0,5,187,4,209, +6,11,16,6,7,61,0,0,0,1,1,47,5,41,3,162,6,72,0,13,0,32,185,0,11,1,3,64,12,4,7,0,185,14,7,80,8,1,80,0,14,16,212,236,220,236,49,0,16,244,60,212,236,48,1,51,30,1,51,50,54,55,51,14,1,35,34,38,1,47,119,11,96,87,85,96,14,119,11,158,145,144,158,6,72,76,74,74, +76,143,144,144,0,1,2,1,5,68,2,206,6,16,0,3,0,20,64,9,2,222,0,221,4,1,97,0,4,16,212,236,49,0,16,244,236,48,1,51,21,35,2,1,205,205,6,16,204,0,0,0,255,255,1,63,5,70,3,145,6,16,16,6,0,106,0,0,0,1,1,153,4,242,3,56,6,198,0,21,0,0,1,50,23,22,21,20,7,6,7,21, +35,53,54,55,54,53,52,35,34,7,53,54,2,74,230,7,1,28,50,52,148,67,49,22,120,90,64,86,6,198,170,5,5,64,36,67,33,88,108,22,48,20,53,94,32,131,24,0,255,255,1,86,4,225,3,123,7,6,16,6,2,119,0,0,0,2,1,88,4,238,4,23,6,102,0,3,0,7,0,37,64,17,6,2,186,4,0,185,8, +0,7,3,4,1,5,7,1,3,8,16,212,220,212,204,17,57,17,18,57,49,0,16,244,60,236,50,48,1,51,3,35,1,51,3,35,2,23,170,224,137,2,12,179,248,135,6,102,254,136,1,120,254,136,0,255,255,1,41,4,238,3,168,6,102,16,6,2,104,0,0,0,1,2,34,4,238,2,170,6,170,0,3,0,0,1,17,35, +17,2,170,136,6,170,254,68,1,188,0,255,255,1,86,4,238,3,118,6,170,16,39,2,149,0,204,0,0,16,7,2,149,255,52,0,0,0,0,0,2,0,210,4,238,3,144,6,102,0,3,0,7,0,0,1,19,35,3,33,19,35,3,1,132,205,135,248,2,0,190,137,223,6,102,254,136,1,120,254,136,1,120,255,255, +1,47,5,41,3,162,6,220,16,39,2,118,0,0,0,204,16,6,2,117,0,0,0,1,1,47,5,41,3,162,6,72,0,13,0,0,1,62,1,51,50,22,23,35,46,1,35,34,6,7,1,47,11,158,144,145,158,11,119,14,96,85,87,96,11,5,41,143,144,144,143,76,74,74,76,0,0,0,0,1,1,213,3,199,3,34,5,32,0,3,0, +0,1,35,19,51,2,196,239,187,146,3,199,1,89,0,0,1,1,239,4,194,2,226,6,193,0,8,0,0,1,16,35,53,22,53,35,53,51,2,225,241,112,112,241,5,195,254,255,123,3,137,254,0,0,0,0,1,1,240,4,194,2,225,6,193,0,8,0,0,1,53,51,21,35,20,51,21,34,1,240,241,112,112,241,5,195, +254,254,134,123,0,0,1,1,219,4,238,2,230,6,102,0,3,0,0,1,51,3,35,2,32,198,113,154,6,102,254,136,0,255,255,1,121,253,184,3,88,255,48,16,7,0,67,0,98,248,202,0,0,255,255,1,121,253,184,3,88,255,48,16,7,0,118,255,158,248,202,0,0,0,1,1,156,253,1,2,212,254,235, +0,7,0,0,1,53,51,17,35,53,35,53,2,76,136,136,176,254,58,177,254,22,177,136,0,0,0,1,1,204,253,1,3,4,254,235,0,7,0,0,1,21,35,17,51,21,51,21,2,84,136,136,176,253,178,177,1,234,177,136,0,0,0,1,1,115,5,134,3,94,7,112,0,5,0,0,1,33,53,33,17,35,2,214,254,158, +1,234,136,6,232,136,254,22,0,1,1,163,2,252,3,46,4,113,0,19,0,0,1,53,30,1,51,50,54,53,52,38,39,51,30,1,21,20,6,35,34,38,1,163,61,88,31,46,46,15,15,133,10,10,87,93,48,105,3,104,119,45,43,55,54,32,62,31,38,68,30,122,115,53,0,0,0,1,1,250,254,10,2,214,255, +193,0,12,0,0,1,21,34,38,52,54,51,21,34,6,21,20,22,2,214,93,127,127,93,51,71,71,254,108,98,128,184,127,98,71,50,51,71,0,0,1,1,98,253,178,3,76,254,235,0,7,0,0,1,51,21,33,53,51,53,51,2,155,177,254,22,177,136,254,58,136,136,177,0,0,0,1,1,94,253,178,3,72, +254,235,0,7,0,0,1,35,53,33,21,35,21,35,2,15,177,1,234,177,136,254,99,136,136,177,0,0,0,1,1,95,253,1,3,73,254,235,0,11,0,0,1,35,53,51,53,51,21,51,21,35,21,35,2,16,177,177,136,177,177,136,253,178,136,177,177,136,177,0,0,0,0,1,1,115,254,99,3,94,254,235, +0,3,0,0,1,53,33,21,1,116,1,234,254,99,136,136,0,0,0,1,1,246,254,86,4,27,0,128,0,13,0,0,37,21,20,7,6,43,1,53,51,50,55,54,61,1,4,27,89,90,165,205,185,90,45,44,128,148,195,105,106,156,62,62,126,148,0,1,0,182,254,86,2,219,0,128,0,13,0,0,55,51,21,20,23,22, +59,1,21,35,34,39,38,53,182,185,44,45,90,185,205,165,90,89,128,148,126,62,62,156,106,105,195,0,0,1,2,1,254,99,2,206,255,47,0,3,0,19,64,8,2,222,0,4,1,97,0,4,16,212,236,49,0,16,212,236,48,5,51,21,35,2,1,205,205,209,204,0,0,2,1,63,254,100,3,146,255,46,0, +3,0,7,0,28,64,13,6,2,222,4,0,8,5,97,4,1,97,0,8,16,212,252,212,236,49,0,16,212,60,236,50,48,5,51,21,35,37,51,21,35,1,64,202,202,1,136,202,202,210,202,202,202,0,2,1,141,254,10,3,68,255,193,0,11,0,23,0,29,181,12,0,18,0,6,24,16,212,204,204,16,204,49,0,181, +15,9,21,9,3,24,16,212,204,204,16,204,48,1,20,6,35,34,38,53,52,54,51,50,22,7,52,38,35,34,6,21,20,22,51,50,54,3,68,127,93,92,127,127,92,93,127,98,71,51,51,70,70,51,51,71,254,230,92,128,128,92,92,127,127,92,50,71,70,51,52,70,71,0,0,0,0,1,1,152,253,226,2, +229,255,59,0,3,0,17,64,6,0,3,4,1,3,4,16,212,204,49,0,16,212,204,48,5,51,3,35,1,246,239,187,146,197,254,167,0,0,1,1,139,254,117,3,41,0,0,0,19,0,56,179,9,6,10,13,186,1,6,0,6,1,5,64,9,0,9,16,19,0,16,124,3,20,16,212,236,212,204,16,196,49,0,47,246,254,197, +18,57,48,1,64,13,73,1,89,1,105,1,121,1,137,1,153,1,6,93,33,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,39,2,188,56,53,120,118,45,87,44,34,75,47,58,61,44,44,62,105,48,89,91,12,12,131,17,15,48,46,30,87,61,0,0,0,255,255,1,174,254,117,3,35,0,0,16, +6,2,120,10,0,0,1,2,36,253,115,2,173,255,47,0,3,0,0,5,17,35,17,2,172,136,209,254,68,1,188,0,0,0,1,1,85,253,229,3,124,255,47,0,7,0,0,5,17,35,53,33,21,35,17,3,124,137,254,235,137,209,254,182,194,194,1,74,0,0,1,0,206,254,57,4,3,255,88,0,20,0,0,1,6,35,34, +3,52,53,51,22,51,50,55,51,22,23,50,55,51,2,7,34,2,104,59,116,218,17,118,13,103,102,16,118,11,105,102,15,118,15,220,116,254,139,82,1,26,2,3,150,150,149,1,150,254,226,1,0,0,0,1,1,41,254,27,3,168,255,147,0,6,0,25,64,11,3,0,186,4,1,7,3,5,11,1,7,16,212,236, +57,49,0,16,212,60,236,57,48,1,3,51,23,55,51,3,2,31,246,139,180,181,139,246,254,27,1,120,245,245,254,136,0,0,0,1,1,41,254,27,3,168,255,147,0,6,0,25,64,11,4,5,2,186,0,7,4,2,11,6,7,16,212,236,57,49,0,16,212,236,50,57,48,5,51,19,35,39,7,35,2,31,147,246,139, +181,180,139,109,254,136,245,245,0,0,1,1,47,254,25,3,162,255,56,0,13,0,32,185,0,11,1,3,64,12,4,7,0,185,14,7,80,8,1,80,0,14,16,212,236,220,236,49,0,16,244,60,212,236,48,5,51,30,1,51,50,54,55,51,14,1,35,34,38,1,47,119,11,96,87,85,96,14,119,11,158,145,144, +158,200,76,74,74,76,143,144,144,0,0,1,1,47,254,27,3,162,255,58,0,13,0,0,1,35,46,1,35,34,6,7,35,62,1,51,50,22,3,162,119,11,96,87,85,96,14,119,11,158,145,144,158,254,27,76,74,74,76,143,144,144,0,1,1,31,254,27,3,178,255,53,0,27,0,134,64,33,0,18,7,14,11, +4,1,18,7,15,11,4,18,204,25,7,4,204,21,11,28,15,1,14,0,7,21,80,22,7,80,8,28,16,212,236,212,236,17,57,57,57,57,49,0,16,212,60,252,212,60,236,17,18,57,17,18,57,17,18,57,17,18,57,48,64,63,9,0,12,10,12,11,12,12,11,15,11,16,15,17,15,18,15,19,15,20,15,21,15, +22,15,23,9,27,25,0,25,1,27,10,27,11,27,12,27,13,27,14,27,15,27,16,27,17,27,18,27,19,31,20,31,21,31,22,26,23,25,27,31,1,93,1,39,46,1,35,34,6,7,35,62,1,51,50,22,31,1,30,1,51,50,54,55,51,14,1,35,34,38,2,100,57,21,33,14,38,36,2,124,1,102,91,39,64,37,57,21, +33,13,39,36,1,125,1,102,91,39,64,254,88,55,20,19,74,81,134,148,28,33,55,20,19,74,81,134,148,28,0,1,1,61,254,155,3,148,255,47,0,3,0,17,182,2,182,0,4,1,0,4,16,212,204,49,0,16,220,236,48,5,33,21,33,1,62,2,86,253,170,209,148,0,255,255,0,0,254,29,4,209,254, +109,16,6,0,66,0,0,255,255,0,0,254,29,4,209,255,93,16,6,7,34,0,0,255,255,0,88,1,236,4,121,3,12,16,6,0,97,0,0,0,1,0,141,1,196,4,38,2,104,0,3,0,0,1,21,33,53,4,38,252,104,2,104,164,164,0,0,0,1,0,0,1,196,4,209,2,104,0,3,0,0,17,53,33,21,4,209,1,196,164,164, +0,1,0,47,255,160,4,150,4,188,0,3,0,0,23,39,1,23,139,92,4,10,93,96,76,4,208,77,0,1,0,8,255,186,4,176,6,23,0,3,0,0,23,39,1,23,111,103,4,68,100,70,70,6,23,74,0,1,1,250,254,10,2,214,255,193,0,12,0,0,1,50,54,53,52,38,35,53,50,22,20,6,35,1,250,51,71,71,51, +93,127,127,93,254,108,71,51,50,71,98,127,184,128,0,0,1,1,85,254,128,3,124,255,202,0,7,0,0,1,17,51,21,33,53,51,17,1,85,137,1,21,137,254,128,1,74,194,194,254,182,0,2,1,85,253,9,3,124,255,47,0,3,0,7,0,0,5,17,33,17,1,17,33,17,3,124,253,217,1,158,254,235, +209,253,218,2,38,254,98,1,22,254,234,0,0,1,0,206,254,57,4,3,255,88,0,20,0,0,5,54,51,50,19,20,21,35,38,35,34,7,35,38,39,34,7,35,18,55,50,2,104,60,116,218,17,117,14,104,101,15,118,12,105,102,15,118,15,220,116,250,82,254,230,2,3,150,150,149,1,150,1,30,1, +0,0,0,0,1,1,139,4,203,3,70,6,135,0,11,0,0,1,7,39,55,39,55,23,55,23,7,23,7,2,104,125,96,125,125,96,125,126,96,125,125,96,5,73,125,96,125,125,97,126,126,97,125,125,96,0,1,1,219,4,194,2,246,6,210,0,29,0,0,1,46,1,53,52,54,55,21,14,1,21,20,23,22,31,1,30,1, +21,20,6,7,53,62,1,53,52,39,38,39,2,24,32,28,146,136,82,74,10,11,19,54,34,28,148,134,82,72,9,11,18,5,199,28,48,28,80,81,2,110,2,27,28,10,12,15,14,43,28,48,28,80,81,2,110,2,27,28,10,12,15,14,255,255,0,0,4,203,4,209,6,11,16,38,7,61,0,0,16,7,7,61,0,0,255, +16,255,255,1,239,4,194,2,226,6,193,16,6,2,155,0,0,255,255,4,2,5,68,4,207,6,16,16,7,2,118,2,1,0,0,0,0,0,1,255,19,5,240,5,190,7,55,0,15,0,0,0,34,5,4,7,35,52,37,54,50,23,4,21,35,38,37,2,160,110,254,226,254,244,126,118,1,252,228,233,229,1,252,118,127,254, +243,6,174,25,23,142,240,60,27,27,60,240,142,23,0,0,1,1,236,4,116,2,235,6,102,0,3,0,0,1,19,51,3,1,236,65,190,110,4,116,1,242,254,14,0,0,0,0,1,1,230,254,86,2,229,0,72,0,3,0,0,37,3,35,19,2,229,65,190,110,72,254,14,1,242,255,255,0,139,0,0,4,70,5,213,18,6, +3,87,0,0,255,255,0,195,0,0,4,26,4,96,18,6,3,119,0,0,0,1,2,30,254,86,2,250,255,164,0,9,0,0,1,35,34,61,1,51,21,20,59,1,2,250,132,88,149,51,20,254,86,183,151,164,104,0,0,0,255,255,0,184,255,227,4,26,4,123,18,6,1,250,0,0,255,255,0,195,255,227,4,37,4,123, +18,38,0,70,0,0,16,7,0,121,0,135,255,132,255,255,0,184,255,227,4,26,4,123,18,38,1,250,0,0,16,6,0,121,138,132,0,0,255,255,1,147,254,225,2,242,4,39,16,6,0,30,0,0,255,255,0,109,255,227,3,188,5,213,18,6,0,45,0,0,255,255,1,219,4,238,3,186,6,102,16,6,0,118, +0,0,255,255,1,63,5,70,3,186,7,216,16,38,0,106,0,0,16,7,2,213,0,0,1,114,255,255,0,25,0,0,4,172,6,102,16,38,2,224,0,0,16,7,2,213,254,62,0,0,255,255,1,233,2,47,2,229,3,96,16,6,0,121,0,0,255,255,255,31,0,0,4,78,6,102,16,38,2,228,0,0,16,7,2,213,253,68,0,0, +255,255,254,237,0,0,4,72,6,102,16,38,2,230,0,0,16,7,2,213,253,18,0,0,255,255,255,31,0,0,4,6,6,102,16,38,2,232,0,0,16,7,2,213,253,68,0,0,255,255,255,181,255,227,4,92,6,102,16,38,2,238,0,0,16,7,2,213,253,218,0,0,255,255,254,112,0,0,4,172,6,102,16,38,2, +243,0,0,16,7,2,213,252,149,0,0,255,255,255,206,0,0,4,135,6,102,16,38,2,247,0,0,16,7,2,213,253,243,0,0,255,255,1,54,0,0,3,207,7,216,16,38,3,7,0,0,16,6,2,214,0,0,0,0,255,255,0,37,0,0,4,172,5,213,16,6,0,36,0,0,255,255,0,166,0,0,4,113,5,213,16,6,0,37,0,0, +255,255,0,215,0,0,4,115,5,213,16,6,3,82,0,0,0,2,0,37,0,0,4,172,5,213,0,2,0,6,0,49,180,3,47,4,48,7,16,244,228,49,0,180,5,180,2,151,4,47,236,228,48,5,64,16,1,37,5,4,0,37,3,6,3,2,37,1,37,4,5,4,7,16,236,236,7,16,236,8,236,37,9,1,5,33,1,51,3,170,254,190,254, +190,3,134,251,121,1,201,245,170,4,121,251,135,170,5,213,0,0,0,255,255,0,197,0,0,4,78,5,213,16,6,0,40,0,0,255,255,0,156,0,0,4,145,5,213,16,6,0,61,0,0,255,255,0,137,0,0,4,72,5,213,16,6,0,43,0,0,0,3,0,117,255,227,4,92,5,240,0,3,0,15,0,27,0,54,64,11,3,4, +50,16,54,2,10,50,22,53,28,16,252,236,196,252,236,196,178,128,3,1,93,49,0,64,15,7,151,25,150,28,1,151,2,177,28,13,151,19,153,28,16,244,236,16,244,236,16,244,236,48,1,33,53,33,23,16,2,35,34,2,17,16,18,51,50,18,19,16,2,35,34,2,17,16,18,51,50,18,3,48,254, +113,1,143,89,135,154,153,135,135,153,154,135,211,247,253,253,246,247,252,253,247,2,199,170,136,1,73,1,26,254,230,254,183,254,184,254,230,1,25,1,73,254,122,254,128,1,126,1,136,1,135,1,128,254,128,0,0,255,255,0,201,0,0,4,6,5,213,16,6,0,44,0,0,255,255,0, +137,0,0,4,201,5,213,16,6,0,46,0,0,0,1,0,37,0,0,4,172,5,213,0,6,0,48,180,4,47,1,48,7,16,244,228,49,0,179,2,180,5,1,47,60,228,48,5,64,16,6,37,2,1,5,37,3,4,3,6,37,0,37,1,2,1,7,16,236,236,7,16,236,8,236,51,35,1,51,1,35,1,246,209,1,201,245,1,201,209,254,141, +5,213,250,43,5,35,0,0,0,255,255,0,86,0,0,4,121,5,213,16,6,0,48,0,0,255,255,0,139,0,0,4,70,5,213,16,6,0,49,0,0,0,3,0,137,0,0,4,72,5,213,0,3,0,7,0,11,0,40,183,7,8,0,49,6,11,3,12,16,212,60,196,244,60,196,49,0,64,12,2,151,3,136,10,5,151,6,177,11,151,10,47, +236,244,236,16,244,236,48,1,21,33,53,1,33,53,33,19,21,33,53,4,72,252,65,2,244,253,215,2,41,203,252,65,5,213,170,170,252,242,170,253,57,170,170,0,0,255,255,0,117,255,227,4,92,5,240,16,6,0,50,0,0,255,255,0,137,0,0,4,72,5,213,16,6,3,94,0,0,255,255,0,197, +0,0,4,117,5,213,16,6,0,51,0,0,0,1,0,120,0,0,4,109,5,213,0,11,0,60,181,2,9,49,5,8,12,16,212,60,228,50,49,0,64,9,11,7,151,8,136,1,5,151,4,47,236,50,244,236,50,48,5,64,16,0,37,6,5,11,37,6,7,6,0,37,1,37,5,6,5,7,16,236,236,7,16,236,8,236,9,1,33,21,33,53,9, +1,53,33,21,33,3,18,254,57,3,34,252,11,1,198,254,58,3,245,252,222,2,235,253,191,170,170,2,65,2,64,170,170,0,0,255,255,0,47,0,0,4,162,5,213,16,6,0,55,0,0,255,255,0,37,0,0,4,172,5,213,16,6,0,60,0,0,0,3,0,117,0,0,4,90,5,213,0,29,0,38,0,47,0,77,64,19,34,50, +5,11,28,9,38,0,30,14,27,25,44,50,20,16,40,25,48,16,212,60,60,220,236,16,196,50,252,60,60,196,50,220,236,49,0,64,20,38,40,151,1,24,0,26,151,27,136,13,30,39,151,9,16,10,14,151,13,47,252,60,220,60,236,50,16,244,252,60,220,60,236,50,48,1,21,22,23,22,21,20, +7,6,7,21,51,21,33,53,51,53,38,39,38,53,52,55,54,55,53,35,53,33,21,3,54,55,54,53,52,39,38,39,3,17,6,7,6,21,20,23,22,2,205,176,97,124,123,97,177,147,254,15,147,177,97,123,123,98,176,147,1,241,147,76,43,67,67,43,76,203,76,42,68,68,42,5,43,118,19,91,115, +235,235,115,90,19,116,170,170,116,19,90,115,235,235,115,91,19,118,170,170,252,163,16,42,68,157,158,68,42,16,253,201,2,55,16,42,68,158,157,68,42,255,255,0,18,0,0,4,190,5,213,16,6,0,59,0,0,0,1,0,117,0,0,4,90,5,213,0,31,0,57,64,15,6,30,7,14,12,0,30,17,31, +25,30,24,19,31,32,16,212,60,212,236,16,196,252,60,196,212,236,49,0,64,13,1,30,151,12,19,13,17,151,6,31,24,136,16,47,228,50,50,252,60,220,60,236,50,48,1,17,54,55,54,25,1,51,17,16,7,6,7,21,51,21,33,53,51,53,38,39,38,25,1,51,17,16,23,22,23,17,2,205,73,46, +75,203,123,98,176,147,254,15,147,176,98,123,203,76,45,73,5,213,252,91,34,87,145,1,68,1,87,254,169,254,120,191,151,32,214,170,170,214,32,151,191,1,136,1,87,254,169,254,188,145,87,34,3,165,0,0,0,0,1,0,74,0,0,4,135,5,180,0,31,0,64,64,23,2,30,27,14,17,113, +21,30,113,27,15,114,21,111,11,112,0,114,27,111,5,108,32,16,244,236,228,244,236,228,16,228,16,228,57,17,18,57,49,0,64,12,24,248,8,247,30,18,14,3,1,249,16,0,47,60,238,23,50,246,238,48,51,53,51,38,2,53,16,0,51,50,0,17,20,2,7,51,21,33,53,54,18,53,52,2,35, +34,2,21,20,18,23,21,74,245,123,110,1,32,240,242,1,33,111,123,248,254,49,120,134,180,154,154,179,134,120,172,134,1,32,188,1,55,1,111,254,146,254,200,188,254,223,133,172,172,76,1,73,222,230,1,9,254,247,230,222,254,183,76,172,0,255,255,0,201,0,0,4,6,7,78, +16,39,12,254,0,0,1,117,16,6,2,232,0,0,255,255,0,37,0,0,4,172,7,78,16,39,12,254,0,0,1,117,16,6,2,243,0,0,255,255,0,70,255,231,4,149,6,102,16,38,2,255,0,0,16,6,2,213,0,0,0,0,255,255,0,169,255,234,4,40,6,102,16,38,3,3,0,0,16,6,2,213,0,0,0,0,255,255,0,195, +254,86,4,27,6,102,16,38,3,5,0,0,16,6,2,213,0,0,0,0,255,255,1,54,0,0,3,207,6,102,16,38,3,7,0,0,16,6,2,213,0,0,0,0,255,255,0,51,0,0,4,105,7,216,16,38,3,19,0,0,16,6,2,214,0,0,0,0,0,2,0,70,255,231,4,149,4,121,0,13,0,42,0,0,1,39,38,39,38,7,6,21,20,23,22,51, +50,55,18,27,1,51,3,23,22,23,22,59,1,21,35,34,39,38,39,6,7,6,39,38,39,38,17,16,55,54,55,2,254,44,45,177,98,61,77,74,77,85,133,72,105,59,99,164,205,40,9,35,41,32,88,110,94,84,41,17,46,92,45,143,198,114,118,126,143,161,2,9,231,236,1,1,111,137,183,220,105, +107,213,3,42,254,189,1,37,253,161,219,49,41,48,156,84,42,88,109,89,42,1,2,150,156,1,20,1,41,135,151,3,0,0,0,0,2,0,151,254,86,4,97,6,33,0,14,0,28,0,0,37,17,35,17,16,5,4,17,2,7,4,19,18,5,6,3,22,23,4,17,16,5,53,4,17,52,39,36,17,1,81,185,1,205,1,143,1,171, +1,22,2,4,254,26,130,171,81,227,1,32,254,48,1,107,234,254,251,69,254,17,6,3,1,231,31,27,254,154,254,236,98,54,254,209,254,61,23,6,1,113,141,21,25,1,39,1,26,22,170,6,1,48,189,13,15,254,224,0,0,0,0,1,0,32,254,86,4,109,4,96,0,14,0,0,19,38,43,1,53,51,50,23, +9,1,51,1,17,35,17,220,45,94,49,70,194,65,0,255,1,70,191,254,91,190,3,68,126,158,176,253,83,3,93,251,160,254,86,1,170,0,0,2,0,137,255,227,4,72,6,34,0,11,0,52,0,0,1,34,6,21,20,22,51,50,54,53,52,38,37,38,39,38,53,52,54,51,50,31,1,21,38,39,38,15,1,6,15,1, +6,21,20,23,22,23,22,23,22,23,22,17,16,2,35,34,2,17,16,55,54,2,104,140,144,144,140,141,144,144,254,89,19,40,62,237,197,102,50,151,66,70,85,82,32,73,60,39,27,13,17,41,24,105,235,121,124,246,234,233,246,123,31,3,223,218,214,213,219,219,213,214,218,76,9, +40,61,92,136,164,12,36,173,24,15,17,2,1,2,43,28,24,46,33,19,24,21,13,1,3,148,151,254,226,254,225,254,211,1,45,1,31,1,30,151,38,255,255,0,169,255,234,4,40,4,123,16,6,2,1,0,0,0,1,0,153,254,82,4,38,6,20,0,29,0,0,37,22,23,22,21,20,7,6,35,52,53,22,55,54,53, +52,39,38,35,32,3,2,1,33,53,33,21,0,19,18,2,248,132,79,84,74,80,163,69,42,32,32,31,58,253,181,20,17,2,76,253,236,3,102,252,254,46,44,127,1,75,79,120,115,80,87,75,76,5,44,35,37,53,44,42,2,51,1,224,1,101,185,185,254,97,254,90,254,105,0,0,1,0,195,254,86, +4,27,4,123,0,19,0,46,64,10,2,6,0,74,13,9,6,11,70,20,16,244,236,50,252,236,49,64,15,9,14,3,0,4,10,6,140,17,190,12,194,1,195,10,0,47,228,228,244,236,17,23,57,48,1,17,35,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,22,4,27,185,106,113,129,139,184,184,49, +168,115,171,169,2,182,251,160,4,96,151,142,183,171,253,135,4,96,168,96,99,225,0,3,0,137,255,227,4,72,5,220,0,8,0,17,0,29,0,57,64,11,9,0,18,21,68,10,8,18,27,62,30,16,244,236,50,252,236,50,49,64,14,9,182,0,14,140,24,0,4,140,18,155,24,153,30,0,16,228,244, +236,196,16,236,182,239,0,191,0,64,0,3,93,16,236,48,1,38,39,38,35,34,7,6,7,5,33,22,23,22,51,50,55,54,1,50,18,17,16,2,35,34,2,17,16,18,3,131,7,63,72,141,140,72,63,7,2,53,253,203,6,64,72,140,141,72,64,254,235,233,247,246,234,233,246,246,3,60,226,135,153, +153,135,226,184,224,137,154,154,137,4,56,254,119,254,141,254,138,254,121,1,135,1,118,1,115,1,137,0,0,1,1,54,0,0,3,207,4,96,0,15,0,29,64,6,6,0,6,15,13,16,16,212,204,252,204,49,64,7,13,182,0,194,6,182,7,0,47,236,244,236,48,1,17,20,23,22,59,1,21,35,34,39, +38,39,17,35,53,2,196,34,36,108,89,111,180,82,81,1,210,4,96,253,43,145,46,48,156,96,98,212,2,59,143,0,0,0,255,255,0,236,0,0,4,178,4,96,18,6,0,250,0,0,0,1,0,68,0,0,4,134,6,21,0,13,0,0,9,1,35,9,1,35,1,39,38,7,35,53,23,4,2,130,2,4,195,254,198,254,126,195, +1,235,74,47,154,49,70,1,18,5,101,250,155,3,60,252,196,4,50,198,127,1,158,2,7,0,255,255,0,195,254,84,4,158,4,96,16,6,0,119,0,0,0,1,0,116,0,0,4,66,4,96,0,20,0,0,33,1,51,1,54,55,54,55,54,39,38,39,51,22,23,22,21,20,7,6,7,1,202,254,170,198,1,33,120,100,76, +4,2,24,28,106,186,69,46,42,136,177,123,4,96,252,84,124,172,129,112,53,100,119,131,89,124,114,78,196,175,228,116,0,0,0,0,1,0,162,254,82,4,56,6,20,0,38,0,0,37,22,23,22,21,20,7,6,35,52,53,22,55,54,53,52,39,38,35,32,3,52,37,36,17,52,55,35,53,33,21,32,17, +20,5,21,4,23,18,3,17,132,79,84,74,80,163,69,42,32,32,32,57,253,146,1,1,77,254,232,220,208,3,21,253,139,2,16,253,199,1,2,127,1,75,79,120,115,80,87,75,76,5,44,35,37,53,44,42,1,225,232,112,36,1,4,197,82,185,185,254,221,191,9,170,38,220,254,191,0,255,255, +0,137,255,227,4,72,4,123,16,6,0,82,0,0,0,1,0,80,255,217,4,158,4,96,0,23,0,0,19,33,21,35,17,20,22,51,50,54,55,21,14,1,35,34,38,53,17,33,17,35,17,35,80,4,49,141,49,55,15,44,7,35,74,37,113,92,254,84,180,143,4,96,184,253,80,72,63,5,1,133,13,12,131,176,2, +156,252,88,3,168,0,2,0,190,254,86,4,84,4,123,0,16,0,28,0,46,64,10,17,18,4,71,23,10,6,12,70,29,16,244,236,50,252,236,49,64,14,10,20,26,140,7,20,140,0,190,7,153,11,195,29,0,16,228,228,244,236,16,238,17,57,48,1,54,23,22,17,16,2,35,34,38,39,17,35,17,16,55, +54,1,52,38,35,34,6,21,20,22,51,50,54,2,132,232,116,116,232,202,102,153,44,185,110,131,1,228,135,133,134,138,138,134,133,135,4,123,1,158,157,254,234,254,239,254,201,87,83,253,201,3,198,1,60,134,157,253,180,214,218,219,213,212,220,218,0,1,0,195,254,82, +4,37,4,123,0,36,0,0,37,22,23,22,21,20,7,6,35,52,53,22,55,54,53,52,39,38,35,32,0,16,0,33,50,22,23,21,46,1,35,34,6,21,20,23,22,2,236,132,79,84,74,80,163,69,42,32,32,31,58,254,252,254,219,1,37,1,4,81,154,78,73,147,93,173,186,93,94,127,1,75,79,120,115,80, +87,75,76,5,44,35,37,53,44,42,1,56,2,40,1,56,42,44,193,65,58,224,208,209,110,111,0,2,0,137,255,227,4,107,4,96,0,13,0,29,0,50,64,10,29,10,18,16,68,4,18,23,62,30,16,244,236,244,236,196,179,14,27,23,16,17,18,57,57,49,64,11,7,140,20,0,14,182,27,194,20,153, +30,0,16,228,244,236,50,16,236,48,1,34,7,6,21,20,22,51,50,54,53,52,39,38,55,22,17,20,7,6,39,34,2,17,16,55,54,51,33,21,2,97,135,70,72,144,140,141,144,172,60,221,206,151,114,215,233,246,123,115,241,2,3,3,167,80,83,213,213,219,219,146,249,129,45,21,162,254, +230,228,167,127,1,1,45,1,31,1,9,153,143,184,0,1,0,159,0,0,4,50,4,94,0,17,0,33,64,7,13,3,15,6,12,10,18,16,212,204,252,196,204,49,0,64,8,15,11,140,12,194,3,182,4,47,236,244,236,50,48,37,22,59,1,21,35,34,39,38,53,17,33,53,33,21,33,17,20,2,230,36,108,89, +111,180,82,82,254,152,3,146,254,146,204,48,156,96,98,212,2,18,182,182,253,227,145,0,0,0,0,1,0,51,0,0,4,105,4,96,0,29,0,0,37,50,55,54,55,54,39,38,39,51,22,23,22,21,20,7,6,37,34,39,38,53,3,35,53,33,17,20,23,22,2,116,150,90,59,15,8,30,28,106,186,70,45,42, +128,133,254,250,180,82,82,1,210,1,143,34,36,156,179,118,187,102,128,119,131,90,123,115,154,225,203,211,1,96,98,212,2,59,143,253,43,145,46,48,0,0,0,2,0,76,254,86,4,133,4,104,0,10,0,41,0,79,64,13,7,18,15,19,3,6,30,22,39,35,18,26,42,16,176,10,75,81,88,220, +27,212,89,236,212,180,48,39,128,39,2,93,60,196,252,60,212,180,48,15,128,15,2,93,236,49,64,16,3,39,140,22,31,0,140,30,11,190,19,22,153,21,195,42,0,16,236,228,50,244,60,236,50,16,236,50,48,1,34,21,17,50,55,54,53,52,39,38,39,50,23,22,17,16,7,6,35,17,35, +17,34,39,38,17,16,55,54,55,21,6,7,6,21,20,23,22,51,17,16,3,5,65,92,86,77,77,71,42,138,119,127,127,129,193,183,199,124,126,126,104,154,65,49,76,76,78,101,3,203,145,253,82,104,93,223,221,99,91,157,132,141,254,217,254,230,150,152,254,110,1,145,153,155,1, +20,1,44,132,109,28,163,26,75,115,190,216,101,103,2,175,1,46,0,0,0,1,0,89,254,86,4,120,4,96,0,23,0,0,5,3,1,35,1,3,38,43,1,53,51,32,23,19,1,51,1,19,22,59,1,21,35,32,2,238,142,254,247,191,1,116,183,47,156,49,70,1,0,67,143,1,10,191,254,139,182,47,157,49, +70,254,255,250,1,122,253,214,3,9,1,229,126,158,176,254,132,2,44,252,244,254,30,126,158,0,0,0,0,1,0,131,254,86,4,78,4,96,0,27,0,0,37,54,55,54,53,17,51,17,20,7,6,7,17,35,17,38,39,38,53,17,51,17,20,23,22,23,17,51,2,196,63,62,84,185,130,121,143,183,143,121, +130,185,84,62,63,183,140,22,64,87,166,2,129,253,120,216,145,135,1,254,111,1,145,1,135,145,216,2,136,253,127,166,87,64,22,3,212,0,0,1,0,70,255,227,4,140,4,96,0,38,0,0,1,18,16,7,6,35,34,38,39,14,1,35,34,39,38,16,19,51,2,17,6,23,22,55,54,55,54,17,51,16, +23,22,23,22,55,54,39,16,3,4,9,131,50,75,186,85,130,21,20,128,88,186,75,50,131,190,126,1,18,41,64,86,34,25,170,25,34,86,64,41,18,1,126,4,96,254,248,253,191,123,185,103,76,72,107,185,123,2,65,1,8,254,237,254,225,226,62,145,2,2,111,82,1,121,254,135,82,111, +2,2,145,62,226,1,31,1,19,0,255,255,1,54,0,0,3,207,6,16,16,38,3,7,0,0,16,6,0,106,0,0,0,0,255,255,0,51,0,0,4,105,6,16,16,38,3,19,0,0,16,6,0,106,0,0,0,0,255,255,0,137,255,227,4,72,6,102,16,38,3,13,0,0,16,6,2,213,0,0,0,0,255,255,0,51,0,0,4,105,6,102,16,38, +3,19,0,0,16,6,2,213,0,0,0,0,255,255,0,70,255,227,4,140,6,102,16,38,3,23,0,0,16,6,2,213,0,0,0,0,0,3,0,150,255,233,4,2,6,36,0,9,0,25,0,35,0,0,1,32,55,54,39,38,7,6,7,6,5,4,3,6,37,36,39,38,3,2,55,54,51,32,19,22,5,6,39,18,23,22,55,54,55,54,1,93,1,12,78,147, +26,31,172,142,73,53,1,237,1,124,192,117,255,0,254,237,116,102,10,9,128,134,210,1,77,50,27,254,142,67,240,6,54,82,165,175,54,87,3,112,65,123,137,161,6,5,165,122,253,250,254,137,225,12,15,198,178,1,151,1,127,202,212,254,130,205,255,30,10,254,253,105,161, +4,4,152,245,0,0,0,0,2,0,116,255,233,4,82,6,36,0,9,0,36,0,0,1,54,39,38,39,38,7,6,23,22,23,4,39,38,55,18,33,50,23,22,3,2,7,6,35,34,39,38,19,23,18,23,22,51,50,55,54,3,139,4,53,74,103,172,31,26,147,78,233,254,221,110,240,29,45,1,82,171,135,128,9,9,128,137, +228,193,159,149,13,195,7,78,114,94,121,100,80,3,112,191,119,166,4,6,161,137,123,65,170,10,75,164,251,1,126,212,200,254,127,254,125,198,213,213,200,1,235,1,254,83,106,156,157,126,0,0,0,1,0,34,0,0,4,167,5,213,0,27,0,0,1,6,3,6,21,17,35,17,52,39,2,39,38, +7,53,54,23,4,19,18,55,54,23,22,7,6,39,38,3,173,113,79,42,203,42,100,92,116,120,76,151,1,15,74,115,229,111,64,122,56,32,118,86,5,17,79,254,250,141,165,253,118,2,138,180,126,1,42,43,52,26,170,24,27,48,254,114,1,137,53,26,49,95,148,84,24,18,0,0,0,255,255, +254,112,0,0,4,167,6,102,16,38,3,31,0,0,16,7,2,213,252,149,0,0,255,255,0,34,0,0,4,167,7,78,16,38,3,31,0,0,16,7,12,254,0,0,1,117,0,3,0,109,254,86,4,100,5,213,0,21,0,30,0,39,0,0,1,35,17,38,39,38,17,16,55,54,55,17,51,17,22,23,22,17,16,7,6,7,53,54,55,54,53, +52,39,38,39,3,17,6,7,6,21,20,23,22,2,196,184,179,104,132,132,93,190,184,178,105,133,133,94,189,86,53,82,82,42,97,184,87,52,81,81,40,254,86,1,147,24,121,150,1,31,1,14,167,118,26,1,97,254,159,24,120,151,254,226,254,242,167,120,25,165,23,71,110,213,188, +135,70,25,252,189,3,67,22,73,109,214,185,138,68,0,0,0,2,0,57,0,0,4,152,4,96,0,13,0,30,0,0,1,33,6,7,2,51,50,3,51,2,55,54,3,38,55,22,23,18,37,38,3,2,35,32,19,54,55,35,53,33,21,3,146,253,176,39,3,4,84,177,5,170,3,175,81,1,1,157,48,6,14,254,228,238,39,40, +237,254,231,11,4,48,65,4,95,3,168,144,253,254,171,1,211,254,43,2,1,1,84,253,144,145,247,253,223,1,1,1,51,254,204,2,32,239,153,184,184,0,0,0,0,1,0,52,254,127,4,145,4,96,0,47,0,0,5,38,39,38,55,7,2,7,6,39,38,55,54,55,54,39,38,35,34,7,53,54,23,22,23,22,7, +55,18,55,54,23,22,7,6,7,6,23,22,51,50,55,2,7,6,39,53,4,3,189,246,33,21,24,189,96,200,141,3,1,61,96,136,91,43,26,142,57,91,82,126,246,33,19,42,189,96,200,141,3,1,61,96,136,91,43,26,142,57,91,38,205,152,173,1,55,10,32,240,156,99,108,254,247,124,89,145, +68,84,132,124,203,169,104,108,224,61,17,34,238,140,112,108,1,9,124,89,145,68,84,132,124,203,169,104,108,253,224,102,77,90,160,160,0,0,0,0,2,0,117,254,86,4,92,5,240,0,10,0,27,0,0,0,16,2,35,34,2,17,16,18,51,50,1,17,38,39,38,17,16,18,51,50,18,17,16,7,6, +7,17,3,137,135,154,153,135,135,153,154,255,0,179,95,123,247,252,253,247,124,94,181,1,160,2,146,1,26,254,230,254,183,254,184,254,230,253,207,1,150,34,148,191,1,136,1,135,1,128,254,128,254,121,254,124,194,149,34,254,106,0,0,2,0,137,254,86,4,72,4,123,0, +11,0,27,0,0,1,34,6,21,20,22,51,50,54,53,52,38,3,17,35,17,38,39,38,17,16,18,32,18,17,16,7,6,2,104,140,144,144,140,141,144,144,49,184,168,96,123,246,1,210,247,123,95,3,223,218,214,213,219,219,213,214,218,252,10,254,109,1,147,26,119,150,1,31,1,30,1,46,254, +210,254,226,254,225,150,118,0,0,0,0,1,0,139,254,82,4,76,5,213,0,35,0,0,1,34,7,6,17,16,18,51,50,23,22,21,20,7,6,35,52,53,22,55,54,53,52,39,38,35,34,39,38,17,16,55,54,41,1,21,2,231,218,77,98,176,129,122,89,84,74,80,163,69,42,32,32,32,57,234,159,123,159, +139,1,50,1,101,5,43,119,152,254,205,254,206,254,208,84,79,120,115,80,87,75,76,5,44,35,37,53,44,42,203,158,1,157,1,110,205,177,170,0,1,0,155,254,82,4,41,4,96,0,35,0,0,1,33,34,7,6,21,20,23,22,23,22,23,22,21,20,7,6,35,52,53,22,55,54,53,52,39,38,35,34,0, +17,16,55,54,41,1,4,41,254,155,193,73,93,93,95,98,133,78,84,74,80,163,69,42,32,32,32,57,187,254,219,147,138,1,12,1,101,3,196,85,108,212,209,110,111,2,2,74,79,120,115,80,87,75,76,5,44,35,37,53,44,42,1,56,1,20,1,40,136,129,0,0,255,255,0,233,0,0,4,88,5,213, +18,6,0,41,0,0,0,1,0,0,254,86,4,6,6,20,0,35,0,0,33,17,52,55,54,51,50,22,23,21,46,1,35,34,7,6,21,17,33,21,33,17,20,7,6,35,34,38,39,53,30,1,51,50,55,54,1,174,136,96,169,49,99,51,36,82,44,120,58,75,1,65,254,191,139,98,173,57,102,46,49,100,48,87,64,82,4,130, +160,142,100,18,18,164,28,29,62,81,111,254,201,143,253,63,146,165,115,21,22,164,31,33,75,95,0,1,0,96,255,252,4,129,5,213,0,23,0,0,1,3,1,3,6,23,22,55,21,34,39,38,55,19,1,19,54,39,38,7,53,50,23,22,1,227,110,3,12,234,39,27,66,131,230,81,95,19,154,253,6,172, +39,27,66,131,230,81,95,4,135,254,91,1,126,253,44,96,42,108,35,189,70,82,182,1,218,254,145,2,144,96,42,108,35,189,70,82,0,1,0,132,0,0,4,77,6,19,0,7,0,0,9,1,35,19,33,1,51,3,4,77,254,231,184,226,253,38,1,25,184,226,3,112,252,144,2,198,3,77,253,93,0,1,0, +33,254,86,4,154,5,240,0,33,0,0,1,17,35,17,6,7,53,54,5,4,19,18,17,16,3,35,18,17,16,39,48,7,6,21,17,35,48,17,16,63,1,38,39,38,1,129,170,98,84,155,1,5,1,66,215,192,224,225,238,60,102,90,203,208,112,140,157,75,5,75,253,140,2,73,10,77,198,102,5,7,254,213, +254,241,253,189,254,55,254,179,1,76,1,202,1,243,91,79,70,235,253,198,2,53,1,2,177,96,182,52,25,0,0,1,0,89,254,144,4,120,4,120,0,22,0,0,1,3,35,1,38,39,1,35,1,38,39,38,35,53,32,23,22,19,18,17,35,16,39,3,80,239,185,1,100,14,50,254,70,185,2,31,98,46,188, +211,1,45,242,224,172,116,168,96,1,52,254,204,1,192,35,77,253,208,2,176,127,33,132,164,216,200,254,80,254,223,254,137,1,94,246,0,0,0,0,1,0,52,255,242,4,145,4,103,0,51,0,0,1,2,7,6,35,34,53,52,1,54,53,52,39,38,35,34,7,53,54,51,50,23,4,17,20,7,55,18,55,54, +51,50,21,20,1,6,21,20,23,22,51,50,55,21,6,35,34,39,36,17,52,55,1,236,96,200,55,34,55,1,36,62,14,26,142,57,91,64,91,26,27,1,29,29,189,96,200,55,34,55,254,220,62,14,26,142,57,91,64,91,26,27,254,227,29,1,153,254,247,124,34,79,154,1,9,138,122,58,54,104,108, +224,48,4,37,254,193,91,77,108,1,9,124,34,79,154,254,247,138,122,58,54,104,108,224,48,4,37,1,63,91,77,0,2,0,190,254,86,4,84,4,123,0,21,0,32,0,0,19,16,55,54,51,54,23,22,17,16,2,35,34,38,39,18,41,1,21,33,32,17,36,16,38,35,34,6,21,20,22,51,50,190,110,129, +215,232,116,116,232,202,102,153,44,5,1,28,1,168,254,104,254,22,2,213,135,133,134,138,138,134,133,2,28,1,60,134,157,1,158,157,254,234,254,239,254,201,87,83,254,115,170,2,218,41,1,172,218,219,213,212,220,0,0,0,255,255,0,195,255,227,4,37,4,123,18,6,0,70, +0,0,255,255,0,186,254,86,3,16,6,20,18,6,0,77,0,0,0,3,0,117,255,227,4,92,5,240,0,8,0,17,0,28,0,0,1,38,39,38,35,34,7,6,7,5,33,18,23,22,51,50,55,54,19,16,2,32,2,17,16,18,51,50,18,3,134,11,53,68,154,153,67,54,11,2,62,253,191,2,66,67,153,154,68,64,214,247, +254,6,246,247,252,253,247,3,113,223,111,141,141,112,222,170,254,213,136,141,141,134,1,79,254,122,254,128,1,126,1,136,1,135,1,128,254,128,0,1,0,162,255,227,4,9,4,123,0,33,0,0,1,38,39,38,35,34,7,6,7,33,21,33,22,23,22,51,50,63,1,21,7,6,35,32,39,38,16,55, +54,33,50,23,22,23,4,9,37,37,99,106,183,102,95,18,2,165,253,91,18,95,102,183,128,77,74,79,104,107,254,244,156,157,157,156,1,12,101,110,40,39,3,174,13,10,26,99,92,169,144,169,92,99,26,25,167,18,22,156,156,2,40,156,156,22,8,12,0,0,0,1,0,162,255,227,4,9, +4,123,0,34,0,0,19,48,53,54,55,54,51,32,23,22,16,7,6,33,34,47,1,53,23,22,51,50,55,54,55,33,53,33,38,39,38,35,34,7,6,162,39,40,110,101,1,12,156,157,157,156,254,244,107,104,79,74,77,128,183,102,95,18,253,91,2,165,18,95,102,183,106,99,37,3,174,163,12,8,22, +156,156,253,216,156,156,22,18,167,25,26,99,92,169,144,169,92,99,26,10,0,0,0,255,255,0,201,0,0,4,141,5,213,18,6,0,160,0,0,255,255,0,190,254,86,4,84,6,31,18,6,0,192,0,0,255,255,0,139,255,227,4,49,5,240,18,6,0,38,0,0,0,1,0,86,0,0,4,121,5,213,0,12,0,0,19, +33,9,1,33,17,35,17,1,35,1,17,35,86,1,14,1,2,1,4,1,15,187,254,246,153,254,245,186,5,213,254,123,1,133,250,43,5,39,254,96,1,160,250,217,0,0,1,0,127,254,86,4,79,4,96,0,12,0,0,19,33,27,1,33,17,35,17,3,35,3,17,35,127,1,27,204,206,1,27,185,226,153,227,185, +4,96,254,123,1,133,251,160,3,178,254,96,1,160,250,164,0,0,2,0,85,254,86,4,84,4,123,0,24,0,35,0,0,1,21,35,53,35,53,51,17,16,55,54,51,54,23,22,17,16,2,35,34,38,39,17,33,21,18,16,38,35,34,6,21,20,22,51,50,1,119,185,105,105,110,131,213,232,116,116,232,202, +102,153,44,1,225,59,135,133,134,138,138,134,133,254,198,112,112,170,2,172,1,62,132,157,1,158,157,254,234,254,239,254,201,87,83,254,227,170,2,147,1,172,218,219,213,212,220,0,1,0,139,255,227,4,49,5,240,0,25,0,0,55,53,30,1,51,50,18,17,16,2,35,34,6,7,53, +62,1,51,32,0,17,16,0,33,34,38,139,73,169,88,197,196,196,197,86,170,74,77,162,91,1,29,1,63,254,195,254,225,91,162,53,207,61,64,1,48,1,50,1,51,1,48,64,61,207,41,41,254,103,254,146,254,144,254,106,41,0,0,255,255,0,139,255,227,4,49,5,240,18,38,3,56,0,0,16, +7,0,121,0,139,0,0,255,255,0,139,255,227,4,49,5,240,16,39,0,121,255,99,0,0,16,6,3,60,0,0,255,255,0,197,0,0,4,78,7,107,16,39,13,1,0,0,1,117,16,6,3,84,0,0,255,255,0,197,0,0,4,78,7,78,16,39,12,254,0,56,1,117,16,6,3,84,0,0,0,1,255,190,254,42,4,111,5,215,0, +47,0,0,1,23,22,51,50,54,53,17,52,38,35,34,7,6,7,6,21,17,35,17,35,53,33,21,33,17,54,55,54,55,54,55,54,51,50,23,22,23,22,21,17,16,7,6,35,34,39,52,2,61,78,13,12,143,113,106,113,106,87,46,22,69,203,246,3,126,254,67,37,48,34,14,64,149,26,22,160,88,14,11,85, +107,105,247,83,17,254,225,17,2,149,203,1,160,151,142,42,21,28,92,171,254,111,5,45,170,170,253,243,42,24,17,9,37,10,2,84,13,16,112,228,254,70,254,232,119,117,2,2,0,255,255,0,215,0,0,4,115,7,107,16,39,12,255,0,72,1,117,16,6,3,82,0,0,0,1,0,139,255,227,4, +49,5,240,0,24,0,76,64,33,0,151,22,177,25,5,179,6,178,3,151,8,17,179,16,178,19,151,14,150,8,153,25,23,0,22,50,17,6,49,11,48,25,16,252,236,50,252,50,204,49,0,16,228,244,236,244,236,16,238,246,238,16,252,238,177,22,19,73,177,3,0,73,80,88,179,22,0,64,2,23, +56,89,48,1,22,18,51,50,55,21,6,35,32,0,17,16,0,33,50,23,21,38,35,34,2,3,33,21,1,94,4,192,189,188,150,154,176,254,225,254,195,1,63,1,29,176,154,152,190,190,163,23,2,115,2,149,228,254,214,125,207,82,1,150,1,111,1,111,1,153,82,207,125,254,244,254,255,170, +0,0,0,255,255,0,139,255,227,4,74,5,240,16,6,0,54,0,0,255,255,0,201,0,0,4,6,5,213,16,6,0,44,0,0,255,255,0,201,0,0,4,6,7,78,16,38,3,69,0,0,17,7,12,254,0,0,1,117,0,8,180,1,18,15,0,7,43,49,0,0,255,255,0,109,255,227,3,188,5,213,16,6,0,45,0,0,0,2,255,237,0, +0,4,199,5,213,0,7,0,29,0,0,37,51,50,54,16,38,43,1,25,1,51,50,4,16,4,43,1,17,35,21,16,2,6,35,53,50,54,18,25,1,3,33,21,90,125,121,94,21,21,144,1,1,254,254,143,207,172,24,202,236,138,118,20,166,142,1,14,149,2,254,253,168,226,254,72,227,5,43,250,254,198, +253,247,238,164,143,1,161,1,87,1,170,0,0,0,2,0,34,0,0,4,199,5,213,0,8,0,28,0,0,37,51,50,54,53,52,38,43,1,3,17,33,17,35,17,51,17,33,17,51,17,51,50,23,22,21,20,4,35,3,33,21,90,125,120,95,21,186,254,117,186,186,1,139,186,21,179,119,103,254,254,143,166,142, +130,140,149,253,41,2,199,253,57,5,213,253,156,2,100,253,168,113,99,234,220,227,0,1,255,190,0,0,4,111,5,215,0,34,0,0,1,17,54,55,54,55,54,55,54,51,50,23,22,23,22,21,17,35,17,52,38,35,34,7,6,7,6,21,17,35,17,35,53,33,21,1,127,37,48,34,14,64,149,26,22,160, +88,14,11,85,203,106,113,106,87,46,22,69,203,246,3,126,5,45,253,243,42,24,17,9,37,10,2,84,13,16,112,228,254,24,1,206,151,142,42,21,28,92,171,254,111,5,45,170,170,0,0,0,255,255,0,137,0,0,4,201,7,107,16,39,12,255,0,27,1,117,16,6,3,89,0,0,255,255,0,139,0, +0,4,70,7,107,16,39,13,1,0,0,1,117,16,6,3,87,0,0,255,255,0,104,0,0,4,129,7,109,16,38,13,6,0,0,16,6,3,98,0,0,0,0,0,1,0,137,254,190,4,72,5,213,0,11,0,0,51,17,51,17,33,17,51,17,33,17,35,17,137,203,2,41,203,254,118,171,5,213,250,213,5,43,250,43,254,190,1, +66,0,0,255,255,0,37,0,0,4,172,5,213,16,6,0,36,0,0,0,2,0,166,0,0,4,113,5,213,0,8,0,23,0,50,64,28,0,151,12,9,151,22,136,1,151,12,20,20,12,8,2,4,0,23,5,50,16,49,10,0,30,22,48,24,16,252,236,50,252,236,196,17,23,57,49,0,47,204,236,244,236,16,236,48,1,17,51, +50,54,53,52,38,35,1,33,17,51,4,23,22,21,20,7,6,41,1,17,33,1,113,239,176,150,158,168,1,204,253,69,235,1,123,101,53,133,133,254,249,254,70,3,134,2,201,253,221,123,141,146,137,2,102,254,62,15,191,100,161,203,103,104,5,213,0,255,255,0,166,0,0,4,113,5,213, +16,6,0,37,0,0,0,1,0,215,0,0,4,115,5,213,0,5,0,24,182,2,49,4,30,1,52,6,16,252,236,236,49,0,180,3,151,1,136,5,47,244,236,48,51,17,33,21,33,17,215,3,156,253,47,5,213,170,250,213,0,0,0,2,0,33,254,190,4,176,5,213,0,15,0,26,0,48,64,13,4,30,1,16,30,15,18,30, +13,5,30,8,27,16,212,236,220,236,212,236,220,236,49,0,64,11,17,151,14,136,1,26,8,151,3,7,5,47,204,50,236,50,50,244,236,48,37,51,17,35,17,33,17,35,17,51,50,19,18,25,1,33,7,33,17,20,3,2,6,21,20,51,33,4,55,121,170,252,197,170,77,48,39,30,3,84,203,254,66, +28,27,11,47,1,209,170,254,20,1,66,254,190,1,236,1,76,1,0,1,13,1,210,170,254,215,224,254,225,254,225,28,8,22,0,0,0,255,255,0,197,0,0,4,78,5,213,16,6,0,40,0,0,0,1,0,15,0,0,4,194,5,213,0,19,0,120,64,11,8,5,4,3,6,9,1,30,12,0,20,16,220,60,252,60,192,23,57, +49,0,64,12,66,8,5,2,3,17,3,0,180,15,10,6,47,60,60,236,50,50,23,57,48,75,83,88,64,9,8,37,9,8,5,7,37,6,5,7,5,237,16,8,237,89,1,64,19,13,0,8,14,0,7,15,0,6,16,0,5,17,0,4,18,0,3,1,16,73,58,73,58,73,58,73,58,73,58,73,58,0,183,12,9,13,8,16,5,19,2,16,60,16,60, +16,60,16,60,1,51,17,1,51,9,1,35,3,7,17,35,17,39,3,35,9,1,51,1,2,11,187,1,28,207,254,225,1,48,197,222,89,187,89,222,197,1,48,254,225,207,1,28,5,213,253,173,2,83,253,166,252,133,2,138,186,254,48,1,208,186,253,118,3,123,2,90,253,173,255,255,0,137,255,227, +4,55,5,240,16,6,0,22,0,0,0,1,0,139,0,0,4,70,5,213,0,9,0,60,64,28,8,4,3,4,3,9,8,9,66,8,2,3,5,180,7,0,9,4,3,8,17,6,49,3,17,1,48,10,16,252,236,252,236,17,57,57,49,0,47,60,236,50,57,57,48,75,83,88,7,16,4,201,7,16,4,201,89,34,51,17,51,17,1,33,17,35,17,1,139, +195,1,248,1,0,195,254,8,5,213,251,51,4,205,250,43,4,205,251,51,0,0,0,255,255,0,139,0,0,4,70,7,109,16,38,13,6,0,0,16,6,3,87,0,0,0,0,255,255,0,137,0,0,4,201,5,213,16,6,0,46,0,0,0,1,0,4,0,0,4,70,5,213,0,15,0,36,64,8,15,30,12,1,30,10,6,16,16,212,220,236, +212,236,49,0,64,9,6,151,5,0,151,11,136,14,5,47,60,244,236,16,236,48,1,21,16,2,6,35,53,50,54,18,25,1,33,17,35,17,1,227,23,203,253,138,118,20,3,46,203,5,43,250,254,187,254,2,238,164,143,1,161,1,87,1,170,250,43,5,43,0,0,0,255,255,0,86,0,0,4,121,5,213,16, +6,0,48,0,0,255,255,0,137,0,0,4,72,5,213,16,6,0,43,0,0,255,255,0,117,255,227,4,92,5,240,16,6,0,50,0,0,0,1,0,137,0,0,4,72,5,213,0,7,0,30,64,9,4,30,1,49,5,30,0,48,8,16,252,236,252,236,49,0,181,4,151,0,136,6,2,47,60,244,236,48,19,33,17,35,17,33,17,35,137, +3,191,203,253,215,203,5,213,250,43,5,43,250,213,0,255,255,0,197,0,0,4,117,5,213,16,6,0,51,0,0,255,255,0,139,255,227,4,49,5,240,16,6,0,38,0,0,255,255,0,47,0,0,4,162,5,213,16,6,0,55,0,0,0,1,0,104,0,0,4,129,5,213,0,20,0,63,64,13,66,8,151,7,153,19,16,136, +21,20,8,16,21,16,212,196,196,49,0,16,228,50,244,236,48,75,83,88,64,18,18,37,0,16,15,19,37,20,20,0,18,37,15,17,37,16,16,15,5,7,16,236,16,236,7,16,236,8,16,236,89,1,6,7,6,7,6,43,1,53,51,50,55,54,55,54,55,1,51,9,1,51,2,229,59,69,44,76,69,92,148,109,81,46, +45,34,14,15,254,88,217,1,55,1,52,213,1,169,158,111,74,43,39,172,47,46,77,32,42,4,53,252,194,3,62,0,0,0,0,3,0,66,0,0,4,143,5,213,0,6,0,24,0,31,0,103,64,15,28,50,12,15,31,9,30,24,4,50,21,18,1,24,32,16,212,60,60,212,236,16,252,60,60,212,236,49,0,64,14,31, +1,151,9,24,7,136,17,25,0,151,15,18,17,47,220,60,236,50,16,244,220,60,236,50,48,1,176,13,75,84,176,16,75,84,91,176,21,75,84,91,176,25,75,84,91,88,191,0,33,0,32,255,192,0,2,0,0,0,32,0,32,0,64,56,18,54,23,56,89,1,17,14,1,21,20,22,19,51,21,4,18,17,16,2,5, +21,35,53,38,2,17,16,18,37,19,62,1,53,52,38,39,2,3,165,73,73,165,203,1,11,182,182,254,245,203,250,199,184,1,9,203,165,73,73,165,1,60,3,123,26,220,199,200,220,4,127,122,10,254,170,254,255,254,252,254,172,10,152,152,10,1,87,1,1,1,4,1,83,10,251,225,26,220, +200,199,220,26,0,255,255,0,18,0,0,4,190,5,213,16,6,0,59,0,0,0,1,0,80,254,190,4,149,5,213,0,11,0,36,64,18,6,2,136,10,8,4,151,11,11,30,8,4,30,6,3,30,0,12,16,212,236,212,236,220,236,49,0,47,236,50,204,236,50,48,51,17,51,17,33,17,51,17,51,17,35,17,80,203, +2,41,203,134,170,5,213,250,213,5,43,250,213,254,20,1,66,0,0,0,0,1,0,137,0,0,4,68,5,213,0,19,0,32,64,16,17,151,6,1,10,136,13,14,9,30,11,3,30,0,48,20,16,252,236,212,236,50,49,0,47,236,50,220,236,48,19,17,51,17,20,22,51,50,54,55,17,51,17,35,17,14,1,35,34, +38,137,203,110,109,117,122,91,203,203,118,150,126,183,175,3,212,2,1,254,25,163,80,29,69,2,120,250,43,2,146,58,23,196,0,0,1,0,114,0,0,4,96,5,213,0,11,0,38,64,10,11,30,10,8,30,6,3,30,1,12,16,212,236,220,236,220,236,49,0,64,8,6,11,2,136,8,4,151,1,47,236, +50,252,60,60,48,41,1,17,51,17,51,17,51,17,51,17,51,4,96,252,18,186,224,186,224,186,5,213,250,213,5,43,250,213,5,43,0,0,1,0,60,254,190,4,176,5,213,0,15,0,47,64,13,15,30,12,11,30,9,7,30,5,3,30,1,16,16,212,236,220,236,220,252,220,236,49,0,64,10,6,9,2,136, +11,8,4,151,14,0,47,204,236,50,50,252,60,60,48,51,17,51,17,51,17,51,17,51,17,51,17,51,17,35,17,60,186,224,186,224,186,134,170,5,213,250,213,5,43,250,213,5,43,250,213,254,20,1,66,0,0,0,0,2,0,32,0,0,4,117,5,213,0,8,0,21,0,42,64,9,4,50,18,14,0,30,9,11,22, +16,212,220,236,50,47,236,49,0,64,12,14,151,8,177,22,10,182,13,136,0,151,9,47,236,244,236,16,244,236,48,37,51,50,54,53,52,38,43,1,3,17,33,53,33,17,51,50,4,21,20,4,35,1,239,138,141,156,157,140,138,202,254,251,1,207,138,251,1,1,254,254,250,166,147,133,133, +148,253,41,5,43,170,253,168,226,221,219,227,0,3,0,65,0,0,4,110,5,213,0,3,0,13,0,24,0,44,64,11,3,30,0,9,50,21,17,4,30,14,25,16,212,236,50,47,236,220,236,49,0,64,11,17,151,13,177,4,151,1,15,136,14,0,47,60,228,50,236,244,236,48,33,17,51,17,37,51,50,55,54, +53,52,38,43,1,3,17,51,17,51,50,4,21,20,4,35,3,163,203,252,157,91,102,78,60,121,119,91,202,202,91,194,1,1,254,254,193,5,213,250,43,166,74,56,150,133,148,253,41,5,213,253,168,226,221,219,227,0,2,0,197,0,0,4,117,5,213,0,8,0,21,0,43,64,24,8,151,12,0,151, +10,136,9,21,13,1,7,4,0,4,50,17,56,0,12,30,10,51,22,16,252,236,50,252,236,17,23,57,49,0,47,228,236,212,236,48,37,51,50,54,53,52,38,43,1,3,17,51,17,51,50,23,22,21,20,7,6,35,1,143,234,141,156,157,140,234,202,202,234,251,128,129,129,129,250,166,147,133,133, +148,253,41,5,213,253,168,113,113,221,219,113,114,0,0,1,0,139,255,227,4,49,5,240,0,27,0,77,64,9,11,9,12,50,25,49,19,2,29,16,220,60,244,236,50,196,49,0,64,23,9,151,12,177,29,3,179,2,178,5,151,0,18,179,19,178,16,151,21,150,0,153,28,16,228,244,236,244,236, +16,238,246,238,16,252,238,177,12,16,73,177,5,9,73,80,88,179,9,12,64,2,23,56,89,48,5,34,39,53,22,51,50,55,54,55,33,53,33,2,39,38,35,34,7,53,54,51,32,23,22,16,7,6,1,213,176,154,150,188,189,96,95,5,253,136,2,115,30,63,98,188,187,152,154,176,1,29,160,159, +159,158,29,82,207,125,147,148,231,170,1,20,97,152,125,207,82,204,205,253,34,203,203,0,2,0,60,255,227,4,149,5,240,0,11,0,30,0,72,64,36,24,23,15,14,4,16,22,3,151,16,150,9,151,22,153,28,26,151,12,177,30,136,28,0,30,19,32,5,30,25,13,26,12,30,28,31,16,220, +236,50,212,50,236,16,75,176,14,81,88,212,27,220,89,236,49,0,47,228,252,238,16,228,238,244,236,17,18,23,57,48,1,16,2,35,34,2,17,16,18,51,50,18,1,51,26,1,51,50,18,17,16,2,35,34,2,3,35,17,35,17,51,3,207,95,107,107,95,95,107,107,95,253,56,111,10,187,202, +202,198,198,202,203,186,10,111,203,203,2,233,1,73,1,26,254,230,254,183,254,184,254,230,1,25,1,164,1,67,1,105,254,128,254,121,254,122,254,128,1,106,1,77,253,102,5,213,0,0,2,0,76,0,0,4,109,5,213,0,8,0,22,0,67,64,13,10,20,0,5,20,30,17,49,0,50,13,9,23,16, +212,212,236,244,236,50,18,17,57,49,0,64,11,66,10,4,151,21,5,151,17,136,19,9,47,60,244,236,212,236,57,48,75,83,88,183,21,37,10,22,37,9,9,10,7,16,5,237,16,237,89,1,20,22,51,33,17,33,34,6,9,1,46,1,53,52,36,51,33,17,35,17,33,1,1,116,142,145,1,15,254,249, +144,151,254,216,1,113,108,178,1,6,246,1,210,203,254,222,254,162,4,37,134,130,2,18,137,251,90,2,154,39,178,178,210,222,250,43,2,119,253,137,0,0,255,255,0,133,255,227,4,35,4,123,16,6,0,68,0,0,0,2,0,125,255,227,4,72,6,55,0,8,0,42,0,54,64,13,34,35,0,18,14, +68,4,18,9,6,20,62,43,16,244,236,236,252,236,212,196,49,0,64,16,7,140,17,34,182,35,30,182,40,2,140,11,190,17,153,43,16,228,244,236,220,236,212,236,16,238,48,1,16,33,32,17,20,22,51,32,1,54,51,50,18,17,16,2,35,34,2,19,54,47,1,38,52,55,54,55,54,55,54,37, +54,55,23,6,15,1,6,7,6,7,3,133,254,227,254,228,144,140,1,29,253,152,120,222,222,247,246,234,233,251,5,1,1,7,5,2,20,36,91,167,128,1,28,51,35,70,35,51,240,98,74,197,21,2,47,1,176,254,80,213,219,3,129,123,254,210,254,225,254,226,254,211,1,51,1,25,45,17,167, +119,82,15,149,73,185,85,65,12,2,16,142,13,5,24,10,43,116,154,0,0,0,0,3,0,209,0,0,4,0,4,96,0,8,0,17,0,32,0,45,64,24,25,0,182,10,32,9,182,18,194,1,182,32,14,18,22,5,18,28,0,9,6,18,70,33,16,252,236,50,212,236,212,236,49,0,47,236,244,236,16,212,236,57,48, +1,17,51,50,54,53,52,38,35,3,17,51,50,54,53,52,38,35,37,33,50,22,21,20,6,7,30,1,21,20,6,35,33,1,137,239,95,101,85,107,243,228,85,84,84,86,254,101,1,141,170,200,95,99,133,109,209,193,254,99,2,3,254,147,112,80,79,94,1,199,254,207,85,67,67,86,150,154,112, +111,129,14,25,136,117,154,168,0,0,0,1,1,1,0,0,3,241,4,96,0,5,0,22,64,10,0,182,3,194,1,4,0,6,2,6,16,220,236,196,49,0,47,252,236,48,1,17,35,17,33,21,1,185,184,2,240,3,202,252,54,4,96,150,0,0,0,2,0,105,254,226,4,104,4,96,0,14,0,24,0,48,64,13,4,6,2,15,6, +14,17,6,12,5,6,8,25,16,212,236,220,236,212,236,220,236,49,0,64,11,16,182,13,194,1,15,8,182,3,7,5,47,204,50,236,50,50,244,236,48,37,51,17,35,17,33,17,35,17,51,50,18,53,17,33,3,17,33,17,20,7,14,1,20,51,3,239,121,150,253,45,150,67,55,32,2,236,185,254,132, +20,8,14,34,150,254,76,1,30,254,226,1,180,1,198,100,1,160,252,54,3,52,254,242,100,247,144,33,26,0,0,0,255,255,0,123,255,227,4,88,4,123,16,6,0,72,0,0,0,1,0,59,0,0,4,151,4,96,0,19,0,120,64,11,8,5,4,3,6,9,1,30,6,0,20,16,220,60,252,60,192,23,57,49,0,64,12, +66,8,5,2,3,17,3,0,194,15,10,6,47,60,60,236,50,50,23,57,48,75,83,88,64,9,8,23,9,8,5,7,23,6,5,7,5,237,16,8,237,89,1,64,19,13,0,8,14,0,7,15,0,6,16,0,5,17,0,4,18,0,3,1,16,73,58,73,58,73,58,73,58,73,58,73,58,0,183,12,9,13,8,16,5,19,2,16,60,16,60,16,60,16, +60,1,51,17,1,51,3,1,35,3,7,17,35,17,39,3,35,1,3,51,1,2,21,168,0,255,199,239,1,3,179,191,104,168,104,191,179,1,3,239,199,0,255,4,96,254,80,1,176,254,108,253,52,2,16,177,254,161,1,95,177,253,240,2,204,1,148,254,80,0,0,255,255,0,169,255,234,4,40,4,123,16, +6,2,2,0,0,0,1,0,195,0,0,4,26,4,96,0,9,0,61,64,10,6,0,6,8,1,5,6,2,70,10,16,252,236,50,212,236,50,49,0,64,8,66,0,5,7,3,194,9,2,47,60,236,50,57,57,48,75,83,88,64,10,0,23,6,5,6,5,23,1,0,1,7,0,16,233,7,16,233,89,9,1,35,17,51,17,1,51,17,35,3,98,254,25,184, +184,1,231,184,184,3,41,252,215,4,96,252,215,3,41,251,160,0,255,255,0,195,0,0,4,26,6,72,16,38,2,142,0,0,16,6,3,119,0,0,0,0,255,255,0,236,0,0,4,178,4,96,18,6,0,250,0,0,0,1,0,30,0,0,4,26,4,96,0,17,0,34,64,8,4,6,1,5,6,17,11,18,16,212,220,236,212,236,49,0, +64,8,5,182,0,194,12,182,11,2,47,60,236,244,236,48,1,33,17,35,17,33,21,20,2,6,43,1,53,51,50,54,18,53,1,9,3,17,184,254,95,27,151,186,55,35,85,94,21,4,96,251,160,3,202,245,189,254,209,233,150,118,1,24,174,0,0,0,0,1,0,61,0,0,4,155,4,96,0,12,0,78,64,21,66, +10,7,2,8,3,0,194,9,6,12,3,7,6,4,13,1,10,6,0,13,16,220,236,50,16,220,236,50,49,0,47,60,196,236,50,17,23,57,48,75,83,88,64,16,8,23,3,7,23,3,2,3,9,23,2,10,23,2,2,1,4,7,16,237,16,5,237,4,7,16,237,16,5,237,89,19,51,9,1,51,17,35,17,1,35,1,17,35,61,184,1,119, +1,119,184,184,254,229,184,254,229,184,4,96,253,77,2,179,251,160,2,229,254,31,1,225,253,27,0,0,1,0,195,0,0,4,26,4,96,0,11,0,36,64,18,1,182,6,9,4,194,10,2,0,8,6,9,1,5,6,3,70,12,16,252,236,50,212,236,50,49,0,47,60,228,50,212,236,48,1,33,17,35,17,51,17,33, +17,51,17,35,3,98,254,25,184,184,1,231,184,184,2,3,253,253,4,96,254,57,1,199,251,160,255,255,0,137,255,227,4,72,4,123,16,6,0,82,0,0,0,1,0,195,0,0,4,26,4,96,0,7,0,28,64,14,1,182,4,194,6,2,0,6,5,1,6,3,70,8,16,252,236,212,236,49,0,47,60,244,236,48,1,33,17, +35,17,33,17,35,3,98,254,25,184,3,87,184,3,202,252,54,4,96,251,160,0,0,255,255,0,190,254,86,4,84,4,123,16,6,0,83,0,0,255,255,0,195,255,227,4,37,4,123,16,6,0,70,0,0,0,1,0,225,0,0,4,7,4,96,0,7,0,28,64,13,0,3,182,5,194,1,7,1,4,3,6,1,8,16,220,252,204,16,204, +49,0,47,252,252,60,48,1,17,35,17,33,53,33,21,2,208,184,254,201,3,38,3,202,252,54,3,202,150,150,0,0,0,255,255,0,104,254,86,4,129,4,96,16,6,0,92,0,0,0,3,0,99,254,86,4,101,6,20,0,6,0,24,0,31,0,99,64,17,29,18,19,13,10,22,25,16,6,13,3,18,10,7,0,13,32,16,212, +60,60,212,236,16,252,60,60,73,59,236,49,0,64,17,25,0,140,16,13,190,26,6,140,22,7,153,24,195,14,155,32,16,236,236,244,60,236,50,244,60,236,50,48,1,176,13,75,84,176,16,75,84,91,88,191,0,33,0,32,255,192,0,2,0,0,0,32,0,32,0,64,56,18,54,23,56,89,1,14,1,21, +20,22,23,21,38,2,17,16,18,55,17,51,17,22,18,17,16,2,7,17,35,19,17,62,1,53,52,38,2,8,120,106,106,120,220,201,199,222,184,222,199,201,220,184,184,120,106,106,3,214,25,153,245,245,162,25,156,22,1,11,1,43,1,43,1,11,22,1,153,254,103,22,254,245,254,213,254, +213,254,245,22,254,115,5,128,252,169,25,162,245,245,153,0,0,0,255,255,0,76,0,0,4,133,4,96,16,6,0,91,0,0,0,1,0,124,254,226,4,94,4,96,0,11,0,36,64,18,9,5,194,2,0,8,182,3,3,6,0,8,6,10,7,6,5,12,16,220,236,212,236,220,236,49,0,47,236,50,204,236,50,48,37,17, +35,17,33,17,51,17,33,17,51,17,4,94,150,252,180,184,1,230,184,150,254,76,1,30,4,96,252,54,3,202,252,54,0,1,0,195,0,0,4,27,4,98,0,19,0,33,64,9,14,9,6,11,3,6,0,70,20,16,252,236,212,236,50,49,0,182,17,182,6,10,1,194,13,47,236,50,220,236,48,19,17,51,17,20, +22,51,50,54,55,17,51,17,35,17,14,1,35,34,38,195,184,107,110,88,114,69,184,184,53,140,139,140,200,2,243,1,111,254,145,100,93,20,39,1,245,251,158,1,210,21,43,163,0,1,0,125,0,0,4,85,4,96,0,11,0,36,64,18,6,11,2,194,8,4,182,1,11,6,10,8,6,6,3,6,1,12,16,220, +236,220,236,220,236,49,0,47,236,50,252,60,196,48,41,1,17,51,17,51,17,51,17,51,17,51,4,85,252,40,168,240,168,240,168,4,96,252,54,3,202,252,54,3,202,0,0,0,0,1,0,80,254,226,4,184,4,96,0,15,0,45,64,13,0,6,13,11,6,10,8,6,6,3,6,1,16,16,220,236,220,236,220, +252,220,236,49,0,64,9,6,11,2,194,8,4,182,15,1,47,204,236,50,252,60,196,48,41,1,17,51,17,51,17,51,17,51,17,51,17,51,17,35,4,34,252,46,168,240,168,240,168,144,150,4,96,252,54,3,202,252,54,3,202,252,54,254,76,0,2,0,30,0,0,4,140,4,96,0,8,0,21,0,41,64,9,4, +18,18,14,0,6,9,11,22,16,212,220,236,50,47,236,49,0,64,11,8,182,14,22,10,182,13,194,0,182,9,47,236,244,236,16,212,236,48,37,51,50,54,53,52,38,43,1,3,17,35,53,33,17,33,50,22,21,20,6,35,1,206,248,124,134,137,121,248,184,248,1,176,1,0,209,237,232,214,156, +88,90,90,90,253,254,3,202,150,254,59,167,168,168,164,0,0,0,0,3,0,104,0,0,4,105,4,96,0,3,0,12,0,23,0,43,64,11,3,6,0,9,18,21,16,4,6,13,24,16,212,236,50,47,236,220,236,49,0,64,10,12,182,16,4,182,1,14,194,13,0,47,60,228,50,236,212,236,48,33,17,51,17,37,51, +50,54,53,52,38,43,1,3,17,51,17,51,50,22,21,20,6,35,3,177,184,252,181,83,124,134,137,121,83,182,182,91,209,237,232,214,4,96,251,160,154,89,91,91,91,253,252,4,96,254,59,167,168,168,164,0,0,0,2,0,195,0,0,4,56,4,96,0,8,0,19,0,42,64,23,8,182,12,0,182,10,194, +9,19,13,1,7,4,0,4,18,16,0,12,6,10,70,20,16,252,236,50,220,236,17,23,57,49,0,47,228,236,212,236,48,37,51,50,54,53,52,38,43,1,3,17,51,17,33,50,22,21,20,6,35,1,123,248,129,128,129,128,248,184,184,1,0,208,237,231,214,153,89,90,94,88,253,254,4,96,254,59,167, +168,168,164,0,0,0,0,1,0,195,255,227,4,37,4,123,0,31,0,75,64,8,10,11,8,18,25,19,0,32,16,220,60,212,236,50,196,49,0,64,22,19,139,18,192,15,0,139,1,192,4,140,29,10,182,8,15,140,22,190,29,153,32,16,228,244,236,220,238,16,254,244,238,16,245,238,177,10,15, +73,177,4,8,73,80,88,179,10,8,64,2,23,56,89,48,55,53,30,1,51,50,55,54,55,33,53,33,38,39,38,35,34,6,7,53,62,1,51,32,0,17,16,7,6,33,34,38,195,65,152,96,172,94,83,9,253,226,2,25,18,69,94,172,93,147,73,78,154,81,1,4,1,37,147,146,254,252,82,157,57,191,62,59, +113,100,176,144,137,82,112,58,65,193,44,42,254,200,254,236,254,236,156,156,43,0,0,0,2,0,78,255,227,4,144,4,123,0,11,0,30,0,63,64,35,24,23,15,14,4,16,22,3,140,16,190,9,140,22,153,28,26,182,12,30,194,28,0,6,19,28,5,6,25,13,26,12,6,28,31,16,220,236,50,212, +50,236,16,212,236,49,0,47,228,220,238,16,228,238,244,236,17,18,23,57,48,1,52,38,35,34,6,21,20,22,55,50,54,1,51,26,1,51,50,18,17,16,2,35,34,2,39,35,17,35,17,51,3,205,112,76,76,113,106,85,85,101,253,57,142,17,210,157,157,223,230,154,153,211,16,142,184, +184,2,63,198,217,244,193,193,234,1,250,1,1,1,0,1,1,254,220,254,211,254,210,254,231,1,20,237,254,28,4,96,0,0,2,0,168,0,0,3,216,4,96,0,8,0,22,0,66,64,12,10,20,0,5,20,8,17,0,18,13,9,23,16,220,212,236,212,236,50,18,17,57,49,0,64,11,66,10,4,182,21,5,182,17, +194,19,9,47,60,244,236,212,236,57,48,75,83,88,183,21,23,10,22,23,9,9,10,7,16,5,237,16,237,89,1,20,22,59,1,17,35,34,6,3,1,46,1,53,52,54,51,33,17,35,17,35,1,1,147,114,55,228,227,56,114,235,1,16,53,170,220,150,1,141,184,193,254,254,3,19,97,85,1,109,86,252, +140,1,223,22,130,167,168,154,251,160,1,199,254,57,255,255,0,123,255,227,4,88,6,109,16,38,3,116,0,0,16,6,0,67,226,7,0,0,255,255,0,123,255,227,4,88,5,191,16,38,3,116,0,0,16,6,0,106,35,175,0,0,0,1,0,35,254,86,4,84,6,20,0,31,0,0,19,53,51,17,51,17,33,21,33, +17,62,1,51,50,22,21,16,2,7,53,54,18,17,52,38,35,34,6,21,17,35,17,35,190,184,1,192,254,64,49,168,124,176,182,250,237,121,173,106,123,138,139,184,3,209,143,1,180,254,76,143,254,115,96,99,230,223,254,180,254,142,46,165,25,1,24,1,22,152,141,183,171,254,251, +3,209,255,255,1,1,0,0,4,11,6,109,16,38,3,114,0,0,16,6,0,118,81,7,0,0,0,1,0,195,255,227,4,37,4,123,0,31,0,76,64,32,13,139,14,192,17,0,139,31,192,28,140,3,22,182,24,17,140,10,190,3,153,32,22,0,21,24,18,13,0,7,70,32,16,244,196,50,252,50,16,196,49,0,16,228, +244,236,220,238,16,254,244,238,16,245,238,177,22,17,73,177,28,24,73,80,88,179,22,24,64,2,23,56,89,48,37,14,1,35,32,39,38,17,16,0,33,50,22,23,21,46,1,35,34,7,6,7,37,21,33,22,23,22,51,50,54,55,4,37,74,157,82,254,252,146,147,1,37,1,4,81,154,78,73,147,93, +173,93,69,18,2,25,253,226,9,83,94,172,96,152,65,57,43,43,156,156,1,20,1,20,1,56,42,44,193,65,58,112,83,137,1,144,176,100,113,59,62,0,0,255,255,0,213,255,227,4,6,4,123,16,6,0,86,0,0,255,255,0,178,0,0,4,68,6,20,16,6,0,76,0,0,255,255,0,178,0,0,4,68,6,16, +16,38,0,243,0,0,17,6,0,106,24,0,0,8,180,3,16,13,6,7,43,49,255,255,0,186,254,86,3,16,6,20,16,6,0,77,0,0,0,2,0,10,0,0,4,203,4,96,0,5,0,30,0,0,37,50,16,43,1,17,23,35,17,35,21,20,2,7,6,43,1,53,51,50,54,18,53,17,33,17,51,50,22,16,6,3,55,208,208,13,21,189, +229,27,82,67,188,39,35,85,94,21,2,53,21,159,237,232,153,1,105,254,151,153,3,202,245,189,254,209,128,105,150,118,1,24,174,1,142,254,59,167,254,176,164,0,0,0,0,2,0,65,0,0,4,158,4,96,0,6,0,24,0,0,37,50,53,52,43,1,25,1,51,50,22,16,6,43,1,17,33,17,35,17,51, +17,33,17,51,3,10,208,208,13,21,159,237,232,164,189,254,148,168,168,1,108,168,153,181,180,254,151,2,2,167,254,176,164,2,3,253,253,4,96,254,57,1,199,0,1,0,35,0,0,4,57,6,20,0,27,0,0,19,53,51,17,51,17,33,21,33,17,62,1,51,50,22,21,17,35,17,52,38,35,34,6,21, +17,35,17,35,190,184,1,192,254,64,49,168,115,171,169,185,106,113,129,139,184,3,209,143,1,180,254,76,143,254,115,96,99,225,228,254,190,1,66,151,142,183,171,254,251,3,209,0,0,255,255,0,236,0,0,4,178,6,109,16,38,3,121,0,0,16,6,0,118,48,7,0,0,255,255,0,195, +0,0,4,26,6,109,16,38,3,119,0,0,16,6,0,67,64,7,0,0,255,255,0,104,254,86,4,129,6,72,16,38,2,142,0,0,16,6,3,130,0,0,0,0,0,1,0,195,254,226,4,26,4,96,0,11,0,0,51,17,51,17,33,17,51,17,33,17,35,17,195,184,1,231,184,254,160,151,4,96,252,54,3,202,251,160,254, +226,1,30,0,0,0,2,0,32,0,0,4,117,5,213,0,7,0,26,0,0,37,51,50,54,16,38,43,1,17,21,51,50,4,21,20,4,35,33,17,33,53,33,53,51,21,33,21,1,239,138,141,156,157,140,138,138,251,1,1,254,254,250,254,172,254,251,1,5,202,1,113,166,147,1,10,148,1,122,212,226,221,219, +227,4,81,164,224,224,164,0,0,0,0,2,0,30,0,0,4,140,6,20,0,17,0,25,0,0,19,53,51,17,51,17,33,21,33,17,33,50,22,16,6,35,33,17,19,51,50,54,52,38,43,1,30,248,184,1,169,254,87,1,0,209,237,232,214,254,72,184,248,124,134,137,121,248,3,205,147,1,180,254,76,147, +254,206,167,254,176,164,3,205,252,207,88,180,90,0,0,0,255,255,0,117,255,227,4,92,5,240,18,6,1,97,0,0,255,255,0,137,255,227,4,72,4,123,18,6,2,27,0,0,0,1,0,215,0,0,4,115,7,7,0,7,0,28,64,14,3,5,151,1,136,7,3,4,49,6,30,1,52,8,16,252,236,252,204,49,0,47,244, +236,204,48,51,17,33,19,51,17,33,17,215,2,242,3,167,253,47,5,213,1,50,254,36,250,213,0,0,0,0,1,1,1,0,0,3,242,5,154,0,7,0,26,64,12,5,0,182,3,194,1,4,7,0,6,2,8,16,220,236,220,204,49,0,47,252,236,204,48,1,17,35,17,33,17,51,3,1,185,184,2,56,185,1,3,168,252, +88,4,96,1,58,254,14,0,0,0,0,1,0,85,0,0,4,115,5,213,0,13,0,0,19,51,17,33,21,33,17,33,21,33,17,35,17,35,85,130,3,156,253,47,2,35,253,221,203,130,3,232,1,237,170,254,189,170,252,194,3,62,0,1,0,127,0,0,3,241,4,96,0,13,0,0,33,17,35,53,51,17,33,21,33,17,33, +21,33,17,1,1,130,130,2,240,253,200,1,160,254,96,1,244,170,1,194,184,254,246,170,254,12,0,0,1,0,215,254,102,4,115,5,213,0,28,0,0,1,17,35,17,33,21,33,17,33,50,23,22,21,17,16,7,6,43,1,53,51,50,55,54,53,17,52,38,35,1,162,203,3,156,253,47,1,55,186,113,111, +104,102,228,76,62,134,56,55,124,124,2,199,253,57,5,213,170,254,70,119,114,238,254,206,254,244,124,122,170,75,75,194,1,34,159,158,0,0,1,1,1,254,86,4,82,4,96,0,29,0,0,1,17,35,17,33,21,33,17,51,32,23,22,21,17,20,7,6,43,1,53,51,50,55,54,53,17,52,39,38,35, +1,185,184,2,240,253,200,250,1,5,72,82,82,81,181,193,172,110,33,38,38,49,134,1,231,254,25,4,96,184,254,207,71,81,229,254,242,214,96,96,156,48,55,147,1,8,170,32,41,0,0,0,0,1,0,15,254,190,4,194,5,213,0,23,0,0,51,9,1,51,1,17,51,17,1,51,1,19,51,17,35,17,35, +3,7,17,35,17,39,3,15,1,48,254,225,207,1,28,187,1,28,207,254,225,246,58,170,27,222,89,187,89,222,3,123,2,90,253,173,2,83,253,173,2,83,253,166,253,47,254,20,1,66,2,138,186,254,48,1,208,186,253,118,0,0,1,0,59,254,226,4,174,4,96,0,23,0,0,51,1,3,51,1,17,51, +17,1,51,3,19,51,17,35,17,35,3,7,17,35,17,39,3,59,1,3,239,199,0,255,168,0,255,199,239,205,77,150,52,191,104,168,104,191,2,204,1,148,254,80,1,176,254,80,1,176,254,108,253,202,254,76,1,30,2,16,177,254,161,1,95,177,253,240,0,0,0,255,255,0,137,254,117,4,55, +5,240,16,38,2,175,183,0,16,6,3,86,0,0,0,0,255,255,0,169,254,117,4,40,4,123,16,38,2,175,189,0,16,6,3,118,0,0,0,0,0,1,0,137,254,190,4,201,5,213,0,15,0,0,37,51,17,35,17,35,1,7,17,35,17,51,17,1,51,1,4,86,114,212,31,254,25,154,203,203,2,119,237,253,187,170, +254,20,1,66,2,236,164,253,184,5,213,253,104,2,152,253,158,0,0,1,0,236,254,226,4,178,4,96,0,15,0,0,37,51,17,35,17,35,1,7,17,35,17,51,17,1,51,1,4,44,134,196,29,254,98,137,190,190,1,227,224,254,71,184,254,42,1,30,2,66,129,254,63,4,96,254,47,1,209,254,90, +0,0,1,0,31,254,190,4,179,5,213,0,15,0,0,37,51,17,35,17,35,17,33,17,35,17,51,17,33,17,51,3,222,213,213,203,253,215,203,203,2,41,203,170,254,20,1,66,2,199,253,57,5,213,253,156,2,100,0,0,0,0,1,0,98,254,226,4,124,4,96,0,15,0,0,37,51,17,35,17,35,17,33,17, +35,17,51,17,33,17,51,3,185,195,195,184,254,25,184,184,1,231,184,184,254,42,1,30,1,249,254,7,4,96,254,67,1,189,0,0,0,0,1,0,113,0,0,4,185,5,213,0,13,0,0,51,17,51,17,33,17,33,21,33,17,35,17,33,17,113,186,1,108,2,34,254,152,186,254,148,5,213,253,156,2,100, +170,250,213,2,199,253,57,0,1,0,125,0,0,4,175,4,96,0,13,0,0,51,17,51,17,33,17,33,21,33,17,35,17,33,17,125,168,1,154,1,240,254,184,168,254,102,4,96,254,57,1,199,150,252,54,2,3,253,253,255,255,0,139,254,117,4,49,5,240,16,38,2,175,100,0,16,6,3,96,0,0,0,0, +255,255,0,195,254,117,4,37,4,123,16,38,2,175,104,0,16,6,3,128,0,0,0,0,0,1,0,47,254,190,4,162,5,213,0,11,0,0,37,51,17,35,17,35,17,33,53,33,21,33,2,207,213,213,203,254,43,4,115,254,45,170,254,20,1,66,5,43,170,170,0,0,0,1,0,225,254,226,4,7,4,96,0,11,0,0, +37,51,17,35,17,35,17,33,53,33,21,33,2,208,195,195,184,254,201,3,38,254,201,184,254,42,1,30,3,174,178,178,0,0,255,255,0,37,0,0,4,172,5,213,16,6,0,60,0,0,0,1,0,92,254,86,4,116,4,96,0,8,0,0,19,51,9,1,51,1,17,35,17,92,195,1,73,1,73,195,254,84,192,4,96,252, +148,3,108,251,178,254,68,1,188,0,0,0,0,1,0,37,0,0,4,172,5,213,0,16,0,0,19,51,9,1,51,1,21,33,21,33,17,35,17,33,53,33,53,37,215,1,108,1,107,217,254,33,1,10,254,246,203,254,248,1,8,5,213,253,109,2,147,252,201,80,170,254,92,1,164,170,80,0,0,0,0,1,0,92,254, +86,4,116,4,96,0,16,0,0,19,51,9,1,51,1,21,51,21,35,21,35,53,35,53,51,53,92,195,1,73,1,73,195,254,84,200,200,192,200,200,4,96,252,148,3,108,251,178,53,150,241,241,150,53,0,0,1,0,18,254,190,4,191,5,213,0,15,0,0,37,51,17,35,17,35,9,1,35,9,1,51,9,1,51,1,4, +88,102,212,5,254,146,254,117,218,1,244,254,80,217,1,72,1,78,217,254,65,170,254,20,1,66,2,131,253,125,3,23,2,190,253,205,2,51,253,66,0,0,1,0,76,254,226,4,134,4,96,0,15,0,0,37,51,17,35,17,35,9,1,35,9,1,51,9,1,51,1,3,250,140,196,18,254,184,254,185,213,1, +184,254,111,204,1,41,1,39,207,254,111,184,254,42,1,30,1,193,254,63,2,72,2,24,254,107,1,149,253,232,0,0,1,0,140,0,0,4,71,5,215,0,28,0,0,1,17,35,17,52,38,35,34,7,6,7,6,21,17,35,17,51,17,54,63,1,54,63,1,50,23,22,23,22,4,71,203,106,113,106,87,46,22,69,203, +203,35,50,48,64,149,48,160,88,14,11,85,1,244,254,12,1,218,151,142,42,21,28,92,171,254,99,5,215,253,85,39,27,26,37,10,2,84,13,16,112,0,255,255,0,195,0,0,4,27,6,20,16,6,0,75,0,0,255,255,0,201,0,0,4,6,5,213,16,6,0,44,0,0,255,255,0,15,0,0,4,194,7,109,16, +38,13,6,0,0,16,6,3,85,0,0,0,0,255,255,0,59,0,0,4,151,6,72,16,38,2,142,0,0,16,6,3,117,0,0,0,0,0,1,0,137,254,102,4,184,5,213,0,30,0,0,1,51,50,23,22,21,17,16,7,6,43,1,53,51,50,55,54,53,17,52,38,43,1,7,17,35,17,51,17,1,51,2,115,24,183,116,111,104,102,228, +76,62,134,56,55,124,124,151,119,203,203,2,119,237,3,113,119,114,238,254,206,254,244,124,122,170,75,75,194,1,34,159,158,127,253,184,5,213,253,104,2,152,0,1,0,236,254,86,4,109,4,96,0,31,0,0,1,51,32,23,22,21,17,20,7,6,43,1,53,51,50,55,54,53,17,52,39,38, +43,1,7,17,35,17,51,17,1,51,2,106,58,1,5,72,82,82,81,181,193,172,110,33,38,38,49,134,221,39,190,190,1,227,224,2,119,71,81,229,254,242,214,96,96,156,48,55,147,1,8,170,32,41,38,254,63,4,96,254,47,1,209,0,0,1,0,137,254,102,4,72,5,213,0,21,0,0,37,16,7,6,43, +1,53,51,50,55,54,53,17,33,17,35,17,51,17,33,17,51,4,72,104,103,227,76,62,134,56,55,253,215,203,203,2,41,203,104,254,242,122,122,170,75,75,194,2,95,253,57,5,213,253,156,2,100,0,1,0,195,254,86,4,26,4,96,0,21,0,0,5,20,7,6,43,1,53,51,50,55,54,53,17,33,17, +35,17,51,17,33,17,51,4,26,82,81,181,193,172,110,33,38,254,25,184,184,1,231,184,20,214,96,96,156,48,55,147,2,13,254,7,4,96,254,67,1,189,0,0,1,0,140,254,190,4,71,5,215,0,32,0,0,37,17,6,15,1,6,15,1,34,39,38,39,38,53,17,51,17,20,22,51,50,55,54,55,54,53,17, +51,17,35,17,35,17,3,124,35,51,47,64,149,48,160,88,14,12,84,203,106,113,106,87,46,21,70,203,203,213,170,2,36,39,27,26,37,10,2,84,13,16,112,228,1,209,254,73,151,142,42,21,28,92,171,1,122,250,41,254,190,1,236,0,1,0,195,254,226,4,27,4,98,0,26,0,0,37,17,6, +7,54,7,6,35,34,38,53,17,51,17,20,22,51,50,54,61,1,51,17,35,17,35,17,3,99,27,60,3,49,84,115,171,169,185,106,113,129,139,184,184,195,184,1,126,51,36,1,28,50,225,228,1,11,254,245,151,142,183,171,206,251,158,254,226,1,214,0,1,1,199,0,0,2,127,6,31,0,3,0,0, +1,17,35,17,2,127,184,6,31,249,225,6,31,0,255,255,0,37,0,0,4,172,7,109,16,38,13,6,0,0,17,6,3,79,0,0,0,24,180,19,8,0,24,7,43,64,13,95,8,80,0,79,8,64,0,47,8,32,0,6,93,49,255,255,0,133,255,227,4,35,6,72,16,38,2,142,0,0,16,6,3,111,0,0,0,0,255,255,0,37,0,0, +4,172,7,78,16,38,3,79,0,0,17,7,12,254,0,0,1,117,0,28,180,5,17,14,10,7,43,64,17,112,14,127,17,48,14,63,17,32,14,47,17,0,14,15,17,8,93,49,0,0,255,255,0,133,255,227,4,35,6,16,16,38,0,106,0,0,16,6,3,111,0,0,0,0,255,255,0,0,0,0,4,156,5,213,16,6,0,136,0,0, +255,255,0,41,255,227,4,176,4,123,16,6,0,168,0,0,255,255,0,197,0,0,4,78,7,109,16,38,13,6,18,0,16,6,3,84,0,0,0,0,255,255,0,123,255,227,4,88,6,72,16,38,2,142,14,0,16,6,3,116,0,0,0,0,255,255,0,117,255,227,4,92,5,240,18,6,1,81,0,0,255,255,0,122,255,227,4, +87,4,123,18,6,1,255,0,0,255,255,0,117,255,227,4,92,7,78,16,39,12,254,0,0,1,117,16,6,3,209,0,0,255,255,0,122,255,227,4,87,6,16,16,38,0,106,0,0,16,6,3,210,0,0,0,0,255,255,0,15,0,0,4,194,7,78,16,39,12,254,0,0,1,117,16,6,3,85,0,0,255,255,0,59,0,0,4,151,6, +16,16,38,0,106,0,0,16,6,3,117,0,0,0,0,255,255,0,137,255,227,4,55,7,78,16,39,12,254,255,239,1,117,16,6,3,86,0,0,255,255,0,169,255,234,4,40,6,16,16,38,0,106,241,0,16,6,3,118,0,0,0,0,255,255,0,26,255,228,4,183,5,213,16,6,1,121,0,0,255,255,0,125,254,76,4, +84,4,96,16,6,2,56,0,0,255,255,0,139,0,0,4,70,7,48,16,38,13,11,0,0,16,6,3,87,0,0,0,0,255,255,0,195,0,0,4,26,5,246,16,38,2,140,0,0,16,6,3,119,0,0,0,0,255,255,0,139,0,0,4,70,7,78,16,39,12,254,0,0,1,117,16,6,3,87,0,0,255,255,0,195,0,0,4,26,6,16,16,38,0,106, +0,0,16,6,3,119,0,0,0,0,255,255,0,117,255,227,4,92,7,78,16,38,3,93,0,0,17,7,12,254,0,0,1,117,0,28,180,12,30,27,18,7,43,64,17,112,27,127,30,48,27,63,30,32,27,47,30,0,27,15,30,8,93,49,0,0,255,255,0,137,255,227,4,72,6,16,16,38,3,125,0,0,17,6,0,106,0,0,0, +20,180,15,30,27,21,7,43,64,9,127,30,112,27,79,30,64,27,4,93,49,255,255,0,117,255,227,4,92,5,240,16,6,3,51,0,0,255,255,0,137,255,227,4,72,4,123,16,6,2,27,0,0,255,255,0,117,255,227,4,92,7,78,16,39,12,254,0,0,1,117,16,6,3,225,0,0,255,255,0,137,255,227,4, +72,6,16,16,38,0,106,0,0,16,6,3,226,0,0,0,0,255,255,0,139,255,227,4,49,7,78,16,39,12,254,255,223,1,117,16,6,3,108,0,0,255,255,0,195,255,227,4,37,6,16,16,38,0,106,236,0,16,6,3,140,0,0,0,0,255,255,0,104,0,0,4,129,7,48,16,38,13,11,0,0,16,6,3,98,0,0,0,0,255, +255,0,104,254,86,4,129,5,246,16,38,2,140,0,0,16,6,3,130,0,0,0,0,255,255,0,104,0,0,4,129,7,78,16,39,12,254,0,0,1,117,16,6,3,98,0,0,255,255,0,104,254,86,4,129,6,16,16,38,0,106,0,0,16,6,3,130,0,0,0,0,255,255,0,104,0,0,4,129,7,107,16,38,13,8,0,0,16,6,3,98, +0,0,0,0,255,255,0,104,254,86,4,129,6,102,16,38,2,147,0,0,16,6,3,130,0,0,0,0,255,255,0,137,0,0,4,68,7,78,16,39,12,254,0,0,1,117,16,6,3,102,0,0,255,255,0,195,0,0,4,27,6,16,16,38,0,106,0,0,16,6,3,134,0,0,0,0,0,1,0,215,254,190,4,115,5,213,0,9,0,0,37,51,17, +35,17,35,17,33,21,33,1,162,213,213,203,3,156,253,47,170,254,20,1,66,5,213,170,0,0,0,0,1,1,1,254,226,3,241,4,96,0,9,0,0,37,51,17,35,17,35,17,33,21,33,1,185,195,195,184,2,240,253,200,184,254,42,1,30,4,96,184,0,0,0,255,255,0,65,0,0,4,110,7,78,16,39,12,254, +0,0,1,117,16,6,3,106,0,0,255,255,0,104,0,0,4,105,6,16,16,38,0,106,0,0,16,6,3,138,0,0,0,0,255,255,0,137,255,227,4,55,5,240,18,6,1,82,0,0,255,255,0,169,255,234,4,40,4,123,18,6,3,3,0,0,255,255,0,117,254,242,4,92,5,240,16,6,0,52,0,0,255,255,0,137,254,82, +4,31,4,119,16,6,0,84,0,0,255,255,0,0,0,0,4,209,5,213,16,6,0,58,0,0,255,255,0,0,0,0,4,209,4,96,16,6,0,90,0,0,0,1,0,119,255,196,4,90,5,213,0,39,0,0,1,30,1,23,62,1,53,17,51,17,20,6,7,30,1,23,7,46,1,39,6,35,34,46,2,53,17,51,17,20,30,2,51,50,55,46,1,39,2, +157,28,83,53,13,9,202,35,34,31,63,32,70,44,88,44,112,168,110,174,121,64,202,19,58,104,86,76,52,61,95,28,1,202,51,95,44,31,64,32,4,74,251,244,92,146,57,18,32,14,158,20,50,29,68,59,120,183,124,4,12,251,182,44,92,76,48,20,54,107,50,0,1,0,128,0,0,4,80,5, +240,0,28,0,0,1,35,53,52,46,2,35,34,14,2,21,17,33,21,33,17,35,17,52,62,2,50,30,2,21,4,42,202,19,58,105,85,86,104,58,19,3,6,252,250,202,64,121,174,220,174,121,64,3,107,223,44,91,75,48,48,75,91,44,254,35,170,254,61,4,12,124,182,120,58,58,120,182,124,0,2, +0,85,0,0,4,124,5,240,0,22,0,38,0,0,1,21,35,17,35,17,33,34,46,2,53,52,62,2,51,50,30,2,21,17,3,52,46,2,35,34,14,2,20,30,2,51,33,4,124,125,202,254,243,106,173,122,66,63,120,173,111,110,175,121,65,202,20,58,106,85,86,104,56,19,19,56,104,86,1,13,2,109,170, +254,61,1,195,62,131,203,141,143,202,128,59,59,128,202,143,254,145,1,181,55,107,84,52,54,98,135,162,135,97,54,0,1,0,54,0,0,4,155,5,240,0,28,0,0,19,52,62,2,50,30,2,21,17,51,21,35,17,35,17,52,46,2,35,34,14,2,29,1,35,54,64,121,174,220,174,121,64,187,187, +202,19,58,105,85,86,104,58,19,202,4,12,124,182,120,58,58,120,182,124,254,97,170,254,61,4,74,44,91,75,48,48,75,91,44,223,0,0,0,0,1,0,128,255,227,4,80,5,213,0,28,0,0,1,20,14,2,34,46,2,53,17,51,17,33,21,33,17,20,30,2,51,50,62,2,61,1,51,4,42,64,121,174,220, +174,121,64,202,3,6,252,250,19,58,104,86,85,105,58,19,202,1,201,124,183,120,59,59,120,183,124,4,12,254,139,170,253,213,44,92,76,48,48,76,92,44,223,0,1,0,96,0,0,4,113,5,240,0,41,0,0,1,20,14,4,7,33,21,33,17,51,21,51,50,62,4,53,52,46,2,34,14,2,29,1,35,53, +52,62,2,50,30,2,4,113,39,64,84,88,88,36,1,103,252,67,203,51,50,118,118,110,85,51,37,77,118,162,118,78,37,203,80,138,188,216,192,143,84,3,127,94,173,153,128,99,65,13,170,1,75,161,49,92,130,161,188,105,127,176,110,48,48,110,176,127,20,20,172,239,148,66, +66,148,239,0,0,0,0,1,0,120,0,0,4,89,5,213,0,9,0,0,37,33,21,33,17,51,17,33,21,33,1,67,2,139,252,170,203,3,22,252,234,170,170,5,213,254,139,170,0,0,0,1,0,128,0,0,4,80,5,242,0,26,0,0,1,35,53,52,46,2,35,34,14,2,21,17,33,21,33,17,52,62,2,50,30,2,21,4,42,202, +19,58,105,85,86,104,58,19,3,6,252,48,64,121,174,220,174,121,64,3,107,223,44,92,76,48,48,76,92,44,252,96,170,4,12,124,183,120,59,59,120,183,124,0,0,2,0,43,255,227,4,166,5,240,0,42,0,58,0,0,0,34,14,2,21,17,35,17,52,62,2,51,50,30,2,29,1,51,21,35,17,20,14, +2,35,34,46,2,52,62,2,59,1,53,52,46,1,2,20,30,2,51,50,62,2,53,17,35,34,14,1,2,133,184,121,72,29,196,69,131,189,120,119,188,131,69,131,131,50,89,123,73,72,122,89,50,50,89,122,72,138,27,70,176,16,34,50,35,34,52,35,17,138,36,51,33,5,76,49,106,171,121,252, +115,3,166,147,220,146,73,75,149,222,147,52,175,254,227,107,165,113,59,51,108,168,234,173,114,56,24,123,173,110,252,218,168,109,63,24,28,65,107,80,1,29,26,64,0,0,2,0,85,255,227,4,124,5,213,0,22,0,38,0,0,1,51,17,51,21,35,17,20,14,2,35,34,46,2,53,52,62, +2,51,33,5,34,14,2,20,30,2,51,50,62,2,53,17,3,53,202,125,125,65,121,175,110,111,173,120,63,66,122,173,106,1,13,254,243,86,104,56,19,19,56,104,86,85,106,58,20,5,213,254,139,170,254,66,143,202,129,59,72,143,214,143,141,216,145,75,170,66,113,147,162,148, +112,67,52,84,107,55,2,5,0,0,1,0,147,0,0,4,61,5,213,0,25,0,0,1,35,53,52,46,2,35,34,14,2,21,17,35,17,51,17,62,1,51,50,30,2,21,4,61,202,19,58,105,85,86,104,58,19,202,202,54,134,79,110,174,121,64,1,238,223,44,92,76,48,48,76,92,44,253,51,5,213,254,80,38,42, +59,120,183,124,0,1,0,154,0,0,4,54,5,213,0,5,0,0,19,51,17,33,21,33,154,203,2,209,252,100,5,213,250,213,170,0,0,1,0,93,255,227,4,116,5,213,0,29,0,0,1,17,20,30,2,50,62,2,53,17,51,17,20,14,2,34,46,2,53,17,35,17,35,17,51,17,2,136,13,36,61,96,58,31,11,186, +26,73,130,210,133,77,29,183,186,186,4,96,253,49,75,102,62,27,27,62,102,75,2,207,253,73,119,171,111,53,53,111,171,119,2,8,252,79,5,213,254,139,0,2,0,54,255,227,4,154,5,240,0,41,0,65,0,0,19,51,21,51,62,3,51,50,30,2,23,21,46,1,35,34,6,7,30,3,21,20,14,4, +35,34,46,2,53,52,54,55,35,19,20,30,4,50,62,4,53,52,46,4,43,1,14,1,54,183,52,47,115,134,150,82,60,93,81,78,45,107,185,79,97,148,56,161,251,173,91,22,52,83,122,164,106,159,205,119,46,47,45,138,253,2,17,37,72,113,166,115,75,42,20,4,11,38,74,127,188,133, +12,43,37,5,213,245,63,101,71,37,9,18,27,18,215,70,54,58,52,4,84,161,239,158,83,157,140,118,84,48,100,175,238,137,128,231,101,254,52,63,121,108,91,66,37,35,63,87,103,117,61,64,121,107,88,64,36,97,235,0,0,0,0,1,0,147,0,0,4,61,5,213,0,25,0,0,33,35,17,14, +1,35,34,46,2,53,17,51,17,20,30,2,51,50,62,2,53,17,51,4,61,202,54,134,79,110,174,121,64,202,19,58,104,86,85,105,58,19,202,1,175,37,42,59,120,183,124,2,143,253,51,44,92,76,48,48,76,92,44,1,88,0,0,1,0,91,255,202,4,118,5,213,0,26,0,0,37,21,1,46,3,53,52,54, +55,54,36,55,3,51,19,14,5,21,20,22,23,4,118,252,222,52,91,67,39,104,123,117,1,15,159,181,238,217,107,203,181,152,110,62,55,60,150,204,1,64,21,47,55,66,40,61,157,103,98,178,86,1,59,254,137,51,113,113,109,96,77,24,26,45,25,0,0,0,0,2,0,95,255,208,4,114,5, +240,0,46,0,57,0,0,1,20,2,7,22,23,7,46,1,39,14,1,35,34,46,2,52,62,2,51,50,22,23,62,1,16,46,2,34,14,2,29,1,35,53,52,62,2,50,30,2,1,34,6,20,22,51,50,54,55,46,1,4,112,94,81,101,76,156,35,72,36,88,205,112,72,120,85,47,47,85,120,72,103,192,88,50,58,37,77,118, +162,118,78,37,203,80,138,188,216,192,143,84,253,66,61,73,71,63,76,143,62,68,139,3,127,169,254,205,124,110,131,102,54,97,45,83,94,38,74,110,144,113,79,41,77,66,97,233,1,4,180,110,49,48,110,176,127,22,22,172,239,148,66,65,147,239,253,107,73,130,72,77,69, +60,69,0,1,0,54,0,0,4,155,5,240,0,26,0,0,19,52,62,2,50,30,2,21,17,51,21,33,17,52,46,2,35,34,14,2,29,1,35,54,64,121,174,220,174,121,64,187,254,123,19,58,105,85,86,104,58,19,202,4,12,124,182,120,58,58,120,182,124,252,158,170,4,74,44,91,75,48,48,75,91,44, +223,0,0,0,0,2,0,86,0,0,4,122,5,240,0,22,0,33,0,0,1,34,6,7,1,21,33,34,46,2,53,52,54,55,54,55,1,51,19,54,36,51,1,14,1,21,20,22,51,33,1,14,1,4,122,109,239,130,1,217,252,246,60,102,73,42,79,90,97,91,254,219,228,194,141,1,24,153,253,51,66,61,100,89,1,162, +254,147,29,57,5,65,183,174,252,200,164,26,56,89,62,80,226,149,163,132,1,254,254,174,175,190,252,122,115,158,51,68,51,2,121,45,94,0,0,1,0,54,255,227,4,155,5,213,0,26,0,0,1,33,21,35,17,20,14,2,34,46,2,53,17,51,17,20,30,2,51,50,62,2,53,3,22,1,133,187,64, +121,174,220,174,121,64,202,19,58,104,86,85,105,58,19,5,213,170,252,158,124,183,120,59,59,120,183,124,4,12,251,182,44,92,76,48,48,76,92,44,0,0,1,0,64,255,227,4,145,5,240,0,57,0,0,1,20,14,2,32,46,2,53,51,20,30,2,50,62,2,53,52,46,2,35,33,53,33,50,62,2,53, +52,38,34,6,21,35,52,62,2,51,50,30,2,21,20,14,2,7,30,3,4,145,60,125,194,254,244,192,124,59,210,33,72,114,160,115,73,35,40,77,113,73,253,176,2,80,66,93,59,26,126,236,121,210,65,118,165,101,100,167,120,67,29,52,76,46,68,99,64,31,1,188,95,171,130,77,77,131, +172,96,65,113,85,49,46,81,108,62,63,102,70,38,170,42,71,90,48,118,112,113,123,91,148,105,56,56,103,145,90,59,104,83,60,15,17,71,96,115,0,0,1,0,54,255,227,4,155,5,213,0,26,0,0,1,20,14,2,34,46,2,53,17,35,53,33,17,20,30,2,51,50,62,2,61,1,51,4,155,64,121, +174,220,174,121,64,187,1,133,19,58,104,86,85,105,58,19,202,1,201,124,183,120,59,59,120,183,124,3,98,170,251,182,44,92,76,48,48,76,92,44,223,0,0,0,1,0,96,255,227,4,113,5,213,0,47,0,0,0,20,30,2,50,62,2,61,1,51,21,20,14,2,34,46,2,53,52,62,2,55,39,46,1,43, +1,53,51,50,22,23,5,21,39,46,3,35,34,14,1,1,51,38,78,119,162,117,77,36,203,80,138,188,216,192,143,84,75,117,139,65,90,56,110,37,45,123,51,126,72,1,251,244,13,40,45,47,21,72,117,83,2,210,252,175,110,50,48,110,175,128,22,22,173,238,148,66,69,150,237,169, +165,242,157,78,2,40,25,18,170,26,30,213,212,103,6,11,9,6,78,144,0,1,0,147,0,0,4,61,5,242,0,24,0,0,33,35,17,52,46,2,35,34,14,2,21,17,35,17,52,62,2,50,30,2,21,4,61,202,19,58,105,85,86,104,58,19,202,64,121,174,220,174,121,64,4,74,44,92,76,48,48,76,92,44, +251,182,4,12,124,183,120,59,59,120,183,124,0,1,0,96,255,198,4,113,5,240,0,39,0,0,0,52,46,2,34,14,2,29,1,35,53,52,62,2,50,30,2,21,20,14,4,35,23,21,1,53,23,30,1,51,50,62,1,3,158,38,78,119,162,117,77,36,203,80,138,188,216,192,143,84,36,62,80,88,90,40,232, +252,251,238,32,94,46,72,117,83,3,1,252,175,110,50,48,110,176,127,22,22,172,239,148,66,69,150,237,169,113,182,144,104,68,33,99,210,1,69,212,101,14,20,78,144,0,1,0,65,0,0,4,144,5,240,0,28,0,0,1,17,35,17,14,3,29,1,35,53,52,62,2,51,50,30,2,21,17,35,17,52, +46,2,2,199,190,86,105,57,18,190,62,134,208,147,157,211,129,55,190,18,57,105,5,71,252,148,3,108,12,73,112,149,88,42,57,130,216,156,86,86,156,216,130,252,92,3,149,79,149,118,79,0,0,2,0,96,0,0,4,112,5,240,0,41,0,68,0,0,1,52,46,2,35,34,46,4,53,52,62,4,51, +50,30,2,21,20,14,2,7,33,21,33,17,51,21,51,50,54,55,62,1,1,52,46,2,35,34,14,4,21,20,30,2,51,50,30,2,21,20,7,62,1,2,134,22,49,78,55,86,118,77,42,20,3,21,48,78,114,153,99,148,202,123,54,68,111,144,76,1,103,252,67,203,40,60,121,57,12,14,1,23,26,69,122,96, +62,94,69,47,27,12,11,37,72,62,76,112,74,37,6,67,82,1,191,50,82,57,31,30,49,65,71,72,32,56,123,118,108,81,48,101,172,226,126,121,229,193,145,37,170,1,76,162,46,43,52,94,1,234,100,170,122,69,32,53,71,79,80,37,41,61,40,20,52,91,123,71,40,42,97,241,0,0,0, +0,1,0,54,0,0,4,155,5,240,0,28,0,0,19,52,62,2,50,30,2,21,17,51,21,35,17,35,17,52,46,2,35,34,14,2,21,17,35,54,64,121,174,220,174,121,64,187,187,202,19,58,105,85,86,104,58,19,202,4,12,124,182,120,58,58,120,182,124,254,97,170,254,61,4,74,44,91,75,48,48,75, +91,44,251,182,0,0,0,1,0,147,255,227,4,61,5,213,0,24,0,0,19,51,17,20,30,2,51,50,62,2,53,17,51,17,20,14,2,34,46,2,53,147,202,19,58,104,86,85,105,58,19,202,64,121,174,220,174,121,64,5,213,251,182,44,92,76,48,48,76,92,44,4,74,251,244,124,183,120,59,59,120, +183,124,0,0,0,0,1,0,33,0,0,4,175,5,213,0,27,0,0,19,51,17,20,30,2,51,50,62,2,53,17,51,17,51,21,33,17,14,1,35,34,46,2,53,33,202,19,58,104,86,85,105,58,19,202,228,254,82,54,134,79,110,174,121,64,4,96,254,168,44,92,76,48,48,76,92,44,2,205,250,213,170,1,175, +37,42,59,120,183,124,0,0,0,0,1,0,105,255,227,4,103,5,240,0,61,0,0,19,51,20,30,2,51,50,62,2,53,52,46,6,53,52,62,2,51,50,30,2,21,35,52,46,2,35,34,14,2,21,20,30,8,21,20,14,2,35,34,46,2,105,210,48,85,116,68,65,109,78,44,66,107,137,144,137,107,66,53,111,168, +116,115,172,113,56,210,28,60,93,65,64,93,61,30,43,73,98,110,115,110,98,73,43,65,126,185,119,123,196,136,72,1,191,75,117,79,41,38,73,106,69,72,96,66,46,48,58,89,129,95,81,145,110,64,64,110,145,81,52,87,62,34,33,59,83,50,53,75,56,41,37,38,49,65,91,122, +82,96,165,121,68,69,125,175,0,1,0,147,0,0,4,61,5,242,0,24,0,0,1,35,53,52,46,2,35,34,14,2,21,17,35,17,52,62,2,50,30,2,21,4,61,202,19,58,105,85,86,104,58,19,202,64,121,174,220,174,121,64,3,107,223,44,92,76,48,48,76,92,44,251,182,4,12,124,183,120,59,59, +120,183,124,0,0,0,0,2,0,64,255,227,4,145,5,240,0,16,0,68,0,0,0,34,14,2,20,30,2,51,50,62,2,52,46,1,39,50,30,2,21,20,14,2,7,30,3,21,20,14,2,32,46,2,53,51,20,30,2,50,62,2,53,52,46,2,35,33,53,33,46,3,53,52,62,2,2,218,144,94,54,22,21,54,94,73,66,93,57,26, +22,54,166,106,168,117,61,29,52,76,46,68,99,64,31,59,125,193,254,244,193,125,59,210,32,71,115,166,115,71,32,40,76,112,73,253,174,1,17,32,49,33,17,61,117,167,5,76,38,65,85,96,89,67,41,41,67,89,96,86,64,202,58,105,148,89,59,102,81,58,15,17,73,98,113,57, +95,172,131,78,77,131,172,96,65,113,85,49,51,86,113,62,58,95,68,37,170,17,57,68,72,31,89,147,106,58,0,0,0,1,0,135,0,0,4,74,5,213,0,7,0,0,1,17,33,21,33,17,35,17,1,82,2,248,253,8,203,5,213,254,139,175,252,79,5,213,0,0,0,3,0,70,0,0,4,138,5,213,0,9,0,19,0, +43,0,0,1,14,3,20,30,2,23,51,62,3,52,46,2,39,3,46,3,16,62,2,55,53,51,21,30,3,16,14,2,7,21,35,2,6,73,97,59,24,25,59,97,72,193,73,98,58,24,24,58,98,73,193,135,174,101,38,39,101,173,135,193,135,174,102,40,40,102,174,135,193,4,179,3,47,103,165,240,169,107, +50,3,3,51,107,168,240,165,103,47,3,251,235,6,87,155,220,1,22,220,156,86,5,122,122,5,86,156,220,254,234,221,156,87,5,157,0,0,0,0,2,0,51,0,0,4,157,5,240,0,29,0,46,0,0,19,17,52,62,2,50,30,2,21,20,14,2,35,34,46,2,39,17,33,21,33,21,35,53,35,53,0,34,14,2,20, +30,2,50,62,2,53,52,46,1,242,55,115,178,246,177,114,54,54,114,177,123,32,74,74,66,23,2,212,253,44,202,191,2,228,156,103,62,25,29,64,105,152,100,59,24,24,60,1,163,2,149,95,161,118,66,68,118,162,94,96,162,119,67,13,27,42,29,254,186,175,244,244,175,3,169, +40,72,102,124,103,75,42,39,72,104,65,62,102,74,255,255,0,117,255,227,4,92,5,240,18,6,0,50,0,0,0,3,0,71,255,227,4,138,5,213,0,41,0,51,0,62,0,0,1,20,14,2,7,14,3,35,34,38,39,46,3,61,1,51,21,20,30,2,51,17,34,38,53,52,62,2,59,1,17,30,3,1,53,34,14,2,20,30, +2,1,52,46,2,35,17,50,62,2,4,138,17,47,80,63,31,69,83,98,59,108,168,60,67,82,44,15,194,15,53,100,85,197,180,44,94,147,103,182,125,172,107,47,253,124,47,67,42,20,20,42,67,1,237,17,54,100,82,82,100,54,17,2,25,84,157,134,105,33,16,21,12,4,24,29,32,105,135, +157,84,19,19,95,150,103,56,3,51,132,139,69,102,67,32,254,139,6,66,137,217,1,170,209,7,22,42,70,41,21,6,253,185,109,156,100,47,252,208,53,102,150,255,255,1,223,3,239,2,242,6,20,18,6,2,100,0,0,0,1,1,214,3,254,2,251,5,213,0,5,0,0,1,51,21,3,35,19,2,40,211, +164,129,82,5,213,152,254,193,1,63,0,0,0,255,255,1,122,4,245,3,89,6,109,18,6,0,118,159,7,0,1,0,225,4,241,3,239,7,37,0,21,0,0,1,35,52,62,2,55,62,3,55,51,20,14,2,7,14,3,1,121,152,41,74,103,61,50,121,106,72,2,152,39,70,95,55,68,132,106,65,4,241,60,108,87, +62,15,12,28,49,79,64,59,106,86,62,15,19,26,44,77,255,255,1,121,4,238,3,88,6,102,18,6,0,67,98,0,0,1,0,178,4,232,4,30,7,21,0,42,0,0,1,35,52,62,2,55,54,51,50,30,2,21,20,14,2,35,34,46,2,39,51,30,1,51,50,62,2,53,52,46,2,35,34,15,1,14,1,1,80,158,55,100,141, +86,61,66,67,132,104,64,34,67,98,64,42,81,71,53,13,165,6,54,30,28,38,23,10,30,52,71,41,50,48,2,130,125,4,241,115,179,131,86,22,15,36,77,118,82,51,89,66,38,21,48,75,54,32,29,17,28,37,20,42,63,42,21,13,1,32,195,0,1,0,188,4,241,4,20,6,20,0,5,0,0,19,17,51, +21,33,21,188,140,2,204,4,241,1,35,169,122,0,0,0,1,0,103,255,229,4,105,4,96,0,39,0,0,37,14,1,35,34,46,2,53,17,51,17,20,22,23,22,51,50,54,53,17,51,17,20,23,22,51,50,55,54,53,17,51,17,35,53,14,1,35,34,2,50,34,104,75,68,93,59,26,168,12,14,25,72,79,60,168, +28,29,74,73,28,29,167,167,33,99,63,150,114,72,69,46,113,192,147,2,137,253,127,119,147,29,57,122,230,2,129,253,127,241,55,56,61,63,228,2,129,251,160,96,60,63,0,1,0,183,254,86,4,25,4,123,0,23,0,0,1,21,35,53,52,38,35,34,6,21,17,33,21,33,17,35,17,51,21,62, +1,51,50,22,4,15,185,106,113,130,138,2,170,253,86,184,184,49,168,115,172,168,2,182,244,244,151,142,182,172,254,22,143,254,86,6,10,168,97,98,224,0,0,2,0,73,254,86,4,135,4,119,0,24,0,32,0,0,37,14,1,35,34,46,2,53,52,62,2,51,50,22,23,53,51,17,51,21,35,17, +35,0,16,22,32,54,16,38,32,3,38,45,152,102,101,161,112,60,60,112,161,101,100,153,46,185,168,168,185,253,230,134,1,12,136,136,254,244,139,84,88,81,151,216,136,138,219,153,82,86,84,147,252,47,143,254,86,4,172,254,82,217,218,1,172,218,0,1,0,114,254,86,4, +94,4,123,0,23,0,0,1,17,51,21,35,17,35,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,22,3,202,148,148,185,106,113,130,138,184,184,49,168,115,172,168,2,182,253,217,143,254,86,4,96,151,142,182,172,253,135,4,96,168,97,98,224,0,0,1,0,164,255,227,4,45,6,20, +0,23,0,0,19,17,51,17,33,21,33,17,20,22,51,50,54,61,1,51,17,35,53,14,1,35,34,38,164,184,2,209,253,47,107,112,131,137,185,185,49,168,114,173,167,1,168,4,108,254,76,143,253,215,151,142,182,172,235,253,48,168,97,100,224,0,0,2,0,73,254,86,4,135,4,119,0,22, +0,30,0,0,37,14,1,35,34,46,2,53,52,62,2,51,50,22,23,53,51,17,51,21,33,0,16,22,32,54,16,38,32,3,38,45,152,102,101,161,112,60,60,112,161,101,100,153,46,185,168,254,159,253,230,134,1,12,136,136,254,244,139,84,88,81,151,216,136,138,219,153,82,86,84,147,250, +135,145,4,172,254,82,217,218,1,172,218,0,1,0,207,0,0,4,1,6,20,0,9,0,0,41,1,17,51,17,33,21,33,17,33,3,172,253,35,184,2,122,253,134,2,37,6,20,254,76,143,252,195,0,0,0,1,0,183,254,86,4,25,4,123,0,21,0,0,1,17,35,17,52,38,35,34,6,21,17,33,21,33,17,51,21,62, +1,51,50,22,4,15,185,106,113,130,138,2,170,252,158,184,49,168,115,172,168,2,182,253,74,2,182,151,142,182,172,252,108,143,6,10,168,97,98,224,0,2,0,66,254,86,4,142,4,123,0,43,0,59,0,0,1,46,3,35,34,14,2,21,17,35,17,51,21,62,3,51,50,30,2,23,51,21,35,14,3, +35,34,46,2,53,52,62,2,51,17,50,62,2,55,35,34,14,2,21,20,30,2,3,127,2,44,85,125,82,77,115,76,39,184,184,34,73,85,100,61,102,167,119,69,5,101,104,11,71,102,122,62,72,115,82,44,53,87,113,60,37,65,51,36,7,196,26,50,40,25,16,34,53,2,47,102,161,113,60,42,90, +143,101,251,235,6,10,170,58,76,45,18,83,153,218,134,143,131,171,102,41,39,74,105,65,78,115,75,37,254,60,32,73,118,86,20,41,61,40,30,53,41,23,0,2,0,73,255,227,4,135,6,20,0,15,0,37,0,0,1,33,34,14,2,21,20,30,2,50,62,2,53,19,17,20,14,2,34,46,2,53,52,62,2, +51,33,17,51,17,51,21,3,38,254,237,59,96,70,38,32,66,101,138,102,67,32,185,54,113,175,240,173,111,52,50,110,173,123,1,21,185,168,3,209,58,108,155,97,101,160,112,59,60,111,160,101,1,162,254,40,115,195,143,81,88,157,215,128,113,203,154,91,1,180,254,76,143, +0,0,0,1,0,188,254,86,4,20,6,20,0,19,0,0,33,35,17,52,38,35,34,6,21,17,35,17,51,17,62,1,51,50,22,21,4,20,185,106,113,130,138,184,184,49,168,115,172,168,2,182,151,142,182,172,251,221,7,190,253,164,97,98,224,229,0,1,1,71,254,86,3,138,4,96,0,5,0,0,1,33,21, +33,17,51,1,255,1,139,253,189,184,254,229,143,6,10,0,1,0,104,254,86,4,104,6,20,0,43,0,0,1,20,23,22,51,50,55,54,53,17,51,17,35,53,14,1,35,34,46,2,61,1,52,39,38,35,34,7,6,21,17,35,17,51,17,62,1,51,50,30,2,21,2,188,28,29,74,73,28,29,167,167,33,99,63,72,92, +51,19,28,29,74,73,28,29,167,167,33,99,63,72,92,51,19,1,223,241,55,56,61,63,228,2,129,251,160,96,60,63,56,106,155,99,252,241,55,56,61,63,228,251,213,7,190,253,236,60,63,56,106,155,99,0,0,0,2,0,137,255,227,4,72,6,43,0,26,0,47,0,0,1,21,35,30,3,21,20,14, +2,34,46,2,53,52,62,2,55,37,19,23,7,5,1,20,30,2,51,50,62,2,53,52,46,2,39,35,34,14,2,4,69,90,33,37,19,4,57,119,181,246,181,118,57,61,105,140,80,254,241,207,148,106,1,65,254,20,30,67,109,80,79,109,68,29,6,27,53,46,153,78,109,68,31,4,96,170,50,111,110,102, +42,122,206,151,85,85,151,206,122,135,203,141,82,15,179,1,33,98,151,210,253,183,83,149,111,65,65,111,149,83,51,111,109,102,42,66,113,151,0,1,0,188,254,86,4,20,6,20,0,19,0,0,19,51,17,20,22,51,50,54,53,17,51,17,35,17,14,1,35,34,38,53,188,184,107,112,131, +137,185,185,49,168,114,173,167,6,20,251,148,151,142,182,172,2,123,249,246,2,82,97,100,224,229,0,0,0,255,255,0,189,0,0,4,21,6,20,18,6,0,75,250,0,0,2,0,171,255,226,4,37,6,20,0,47,0,68,0,0,1,21,14,1,7,30,3,21,17,35,53,14,3,35,34,46,2,53,52,18,55,46,3,53, +52,54,63,1,51,7,6,21,20,30,2,51,50,55,62,1,1,20,30,2,51,50,62,2,61,1,52,46,2,39,14,3,3,68,21,41,21,90,119,71,28,184,20,63,85,104,59,89,139,96,51,196,182,57,84,56,27,17,18,51,199,57,32,20,36,50,31,34,32,27,56,254,67,27,57,87,61,77,108,67,31,20,54,95,75, +57,99,73,42,5,44,177,13,27,14,53,126,146,164,91,253,255,172,44,74,54,30,66,118,166,101,193,1,96,155,7,45,63,78,40,32,63,28,79,85,48,49,27,48,36,21,11,18,36,252,170,69,118,86,49,55,93,123,68,86,51,121,119,108,39,53,123,137,149,0,0,0,1,0,114,254,86,4,95, +4,123,0,21,0,0,1,17,51,21,33,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,22,3,202,149,254,178,106,113,130,138,184,184,49,168,115,172,168,2,182,252,47,143,4,96,151,142,182,172,253,135,4,96,168,97,98,224,0,0,2,0,159,255,227,4,50,6,20,0,42,0,61,0,0,1, +50,30,2,23,21,46,1,35,34,14,2,7,30,3,21,17,35,53,14,3,35,34,46,2,53,52,18,55,35,53,51,62,3,1,20,30,2,51,50,62,2,61,1,52,46,2,39,6,2,3,197,10,25,24,19,6,20,56,26,54,106,100,93,40,120,192,135,73,184,24,63,81,102,62,92,136,91,45,56,54,145,210,50,125,150, +173,254,24,39,67,88,48,75,103,63,28,45,98,154,109,49,56,6,20,2,3,4,2,151,9,10,42,77,110,68,10,79,134,183,114,253,172,168,44,72,52,29,64,113,154,90,146,1,43,140,143,94,160,117,65,251,159,88,117,70,29,60,97,121,61,139,76,129,96,58,7,118,254,238,0,1,0,104, +255,227,4,104,6,20,0,21,0,0,19,17,51,17,20,22,51,50,54,53,17,33,21,35,17,35,53,14,1,35,34,38,104,184,107,112,131,137,1,97,168,185,49,168,114,173,167,1,168,2,184,253,72,151,142,182,172,4,47,143,250,123,168,97,100,224,0,0,0,1,1,61,254,86,3,147,4,96,0,10, +0,0,1,51,17,20,6,43,1,53,51,50,53,2,219,184,178,166,254,234,180,4,96,251,140,196,210,156,250,0,0,0,0,1,0,104,255,227,4,104,6,20,0,21,0,0,1,17,35,53,33,17,20,22,51,50,54,53,17,51,17,35,53,14,1,35,34,38,1,16,168,1,96,107,112,131,137,185,185,49,168,114, +173,167,1,168,3,221,143,251,148,151,142,182,172,2,123,251,160,168,97,100,224,0,0,1,0,173,254,86,4,35,4,124,0,49,0,0,5,20,30,2,51,33,21,33,34,46,2,53,52,62,6,53,52,46,2,35,34,14,2,7,39,62,1,51,50,30,2,21,20,14,6,1,129,7,20,32,26,2,27,253,116,42,68,48, +26,60,99,126,132,126,99,60,39,75,109,71,35,73,69,61,22,136,69,206,129,106,174,123,67,58,95,121,126,121,95,58,207,8,26,24,18,143,27,47,63,36,50,109,115,122,126,131,133,135,68,59,96,67,36,19,37,54,34,101,90,107,55,105,153,99,75,149,144,137,126,113,96,76, +255,255,0,189,0,0,4,21,4,123,18,6,0,81,250,0,0,1,0,242,254,86,3,222,4,146,0,47,0,0,1,33,21,33,34,46,2,53,52,62,4,55,34,46,2,53,52,54,63,1,23,7,14,1,21,20,30,2,51,50,54,55,23,14,3,21,20,30,2,2,15,1,207,253,190,35,61,47,27,34,60,82,96,107,54,45,109,96, +65,49,55,95,123,31,45,61,41,66,81,39,35,62,23,63,112,189,138,77,12,23,32,254,229,143,21,43,65,44,58,136,144,147,139,128,52,32,69,108,76,60,123,55,96,113,30,44,96,47,39,56,37,17,11,9,113,90,215,213,190,65,21,39,30,18,0,0,0,1,0,103,254,86,4,105,4,96,0, +39,0,0,37,14,1,35,34,46,2,53,17,51,17,20,22,23,22,51,50,54,53,17,51,17,20,23,22,51,50,55,54,53,17,51,17,35,17,14,1,35,34,2,50,34,104,75,68,93,59,26,168,12,14,25,72,79,60,168,28,29,74,73,28,29,167,167,33,99,63,150,114,72,69,46,113,192,147,2,137,253,127, +119,147,29,57,122,230,2,129,253,127,241,55,56,61,63,228,2,129,249,246,2,10,60,63,0,0,0,0,2,0,168,254,86,4,41,4,124,0,46,0,70,0,0,1,20,14,6,21,20,30,2,51,33,21,33,34,46,2,53,52,54,55,62,3,53,52,46,4,53,52,62,2,51,50,30,2,37,34,14,2,21,20,30,4,21,20,7, +62,3,53,52,46,2,4,41,58,95,121,126,121,95,58,19,26,29,11,2,27,253,116,38,67,49,29,82,72,29,32,16,3,36,55,64,55,36,73,120,154,80,102,173,125,70,254,42,43,86,68,42,31,45,54,45,31,50,63,131,107,68,41,75,105,2,235,79,154,145,137,125,112,95,78,29,22,29,18, +7,143,25,43,57,32,66,144,73,29,59,61,64,35,53,90,82,76,81,89,52,79,134,96,54,53,103,149,151,27,52,78,51,33,65,68,70,76,82,44,81,79,61,130,137,145,75,63,96,66,33,0,0,0,1,0,132,0,0,4,77,4,123,0,36,0,0,1,34,14,2,21,17,35,17,51,21,62,1,51,50,30,2,21,20,14, +2,7,33,21,33,53,62,3,53,52,46,2,2,59,62,96,64,33,184,184,49,162,121,99,142,90,43,28,55,82,53,1,41,253,253,63,92,60,29,26,61,99,3,219,52,90,122,70,253,115,4,96,172,100,99,70,125,174,103,83,144,130,118,57,143,132,52,109,121,138,80,73,129,97,56,255,255, +0,189,255,227,4,21,4,94,18,6,0,88,250,0,0,1,0,102,254,86,4,106,6,20,0,21,0,0,19,17,51,17,20,22,51,50,54,53,17,51,17,51,21,33,17,14,1,35,34,38,102,184,107,112,131,137,185,172,254,155,49,168,114,173,167,1,168,2,184,253,72,151,142,182,172,4,47,248,211,145, +2,82,97,100,224,0,0,1,0,104,255,229,4,105,4,123,0,44,0,0,33,35,17,52,39,38,35,34,7,14,1,21,17,35,53,14,1,35,34,46,2,53,17,51,17,20,23,22,51,50,55,54,53,17,51,21,62,1,51,50,30,2,21,4,105,168,28,29,74,73,28,13,16,167,33,99,63,71,91,52,20,168,28,29,74,73, +28,29,167,33,99,63,71,91,52,20,2,129,241,55,56,61,29,128,101,253,94,96,60,63,54,106,157,103,2,215,253,127,241,55,56,61,63,228,2,129,96,60,63,54,106,157,103,0,0,1,0,188,254,86,4,20,4,123,0,19,0,0,1,17,35,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,22, +4,20,185,106,113,130,138,184,184,49,168,115,172,168,2,182,253,74,2,182,151,142,182,172,251,221,6,10,168,97,98,224,0,0,255,255,0,157,254,72,4,52,4,123,18,6,0,74,34,0,0,1,0,249,0,0,3,215,4,96,0,5,0,0,37,33,21,33,17,51,1,177,2,38,253,34,184,143,143,4,96, +0,0,1,0,104,254,86,4,105,6,20,0,44,0,0,33,35,17,52,39,38,35,34,7,14,1,21,17,35,17,14,1,35,34,46,2,53,17,51,17,20,23,22,51,50,55,54,53,17,51,17,62,1,51,50,30,2,21,4,105,168,28,29,74,73,28,13,16,167,33,99,63,71,91,52,20,168,28,29,74,73,28,29,167,33,99, +63,71,91,52,20,2,129,241,55,56,61,29,128,101,251,180,2,10,60,63,54,106,157,103,2,215,253,127,241,55,56,61,63,228,4,53,253,236,60,63,54,106,157,103,0,0,0,0,2,0,87,254,86,4,122,4,123,0,28,0,38,0,0,37,17,33,21,33,21,35,53,35,53,51,17,51,21,62,1,51,50,30, +2,21,20,14,2,35,34,38,0,16,38,35,34,6,16,22,51,50,1,136,2,242,253,14,185,120,120,185,46,153,100,101,161,112,60,59,112,161,102,103,151,1,239,134,134,135,137,137,135,134,141,254,187,143,99,99,143,5,24,143,84,86,82,153,219,138,135,217,151,81,86,1,31,1,174, +217,218,254,84,218,0,255,255,0,137,255,227,4,72,4,123,18,6,0,82,0,0,0,3,0,40,254,86,4,168,6,20,0,36,0,43,0,54,0,0,1,20,14,2,35,17,35,17,34,46,2,39,55,30,3,51,17,34,46,2,53,52,62,2,59,1,17,50,30,2,1,17,34,6,21,20,22,1,52,46,2,35,17,50,62,2,4,168,56,122, +195,139,184,75,128,110,98,45,123,33,71,80,93,56,98,155,110,58,58,111,159,102,175,138,194,123,57,253,72,125,116,123,2,121,29,75,128,99,94,127,77,33,2,67,130,215,154,85,254,91,1,165,30,55,80,50,128,44,74,53,29,3,46,45,80,112,67,72,112,77,39,254,71,72,137, +200,1,153,1,43,79,72,66,82,253,229,90,140,96,50,252,210,66,117,161,0,0,1,0,72,255,227,4,136,6,20,0,21,0,0,19,17,51,17,20,22,51,50,54,53,17,51,17,51,21,33,53,14,1,35,34,38,72,184,107,112,131,137,185,232,254,95,49,168,114,173,167,1,168,4,108,251,148,151, +142,182,172,2,123,252,47,143,168,97,100,224,0,0,0,2,1,255,0,0,2,210,3,82,0,3,0,7,0,0,37,51,21,35,17,51,21,35,1,255,211,211,211,211,254,254,3,82,254,0,0,1,1,100,1,164,3,109,2,131,0,7,0,0,1,22,36,55,21,6,4,39,1,100,131,1,2,132,131,254,252,130,2,131,63, +6,57,164,56,6,62,0,0,0,0,2,0,49,255,217,4,150,7,34,0,36,0,47,0,0,1,22,23,22,21,35,52,39,38,39,51,22,23,22,55,54,55,54,53,51,20,23,22,23,22,54,53,51,20,7,6,35,34,39,6,7,6,1,39,3,35,1,35,53,51,1,19,5,2,151,15,10,21,114,24,31,97,123,30,25,12,30,46,5,3,114, +9,13,29,38,18,113,25,44,98,83,21,32,33,29,1,191,158,246,127,254,6,47,148,1,211,219,1,35,6,22,49,50,106,255,238,123,162,205,64,69,35,4,7,36,28,93,124,14,21,1,1,48,113,171,33,60,34,28,7,5,252,201,53,252,199,6,68,131,250,65,2,219,98,0,0,2,0,49,255,217,4, +150,7,41,0,42,0,53,0,0,1,21,6,7,6,21,20,23,22,23,21,34,7,6,21,20,23,22,51,50,55,54,55,21,6,7,6,35,34,39,38,53,52,55,54,55,38,39,38,39,38,55,54,1,39,3,35,1,35,53,51,1,19,5,3,124,76,65,86,58,50,49,56,85,71,30,38,47,61,56,79,54,45,78,64,63,95,70,63,68,40, +55,45,28,34,1,1,142,71,1,113,158,246,127,254,6,47,148,1,211,219,1,35,7,41,94,10,29,37,36,20,32,27,2,92,42,36,64,46,33,42,13,18,24,110,20,16,13,70,63,92,75,72,42,14,18,27,32,35,84,72,35,251,195,53,252,199,6,68,131,250,65,2,219,98,0,0,4,0,90,0,0,4,119, +5,20,0,3,0,7,0,11,0,15,0,0,37,51,21,35,37,51,21,35,1,51,21,35,37,51,1,35,3,195,180,180,254,152,180,180,254,13,180,180,2,148,160,253,94,160,250,250,250,250,5,20,250,250,250,236,0,5,0,0,0,0,4,209,5,20,0,3,0,7,0,11,0,15,0,19,0,0,37,51,21,35,37,51,21,35, +37,51,21,35,1,51,21,35,37,51,1,35,4,29,180,180,254,182,180,180,254,182,180,180,254,133,180,180,1,204,160,254,38,160,250,250,250,250,250,250,5,20,250,250,250,236,0,1,1,214,0,0,2,251,1,236,0,5,0,0,33,35,53,19,51,3,2,169,211,164,129,82,172,1,64,254,192, +0,0,2,1,100,4,253,3,109,6,241,0,10,0,27,0,0,1,51,50,55,54,53,52,39,6,7,6,23,43,1,53,51,17,51,17,54,55,54,23,22,21,20,7,6,2,53,55,77,23,53,30,15,57,51,23,175,112,81,102,36,104,63,70,65,64,54,5,98,13,33,21,31,16,4,22,20,169,101,1,143,254,191,73,40,24,26, +25,82,91,50,42,0,0,2,1,214,0,0,2,251,5,17,0,5,0,9,0,0,1,35,53,19,51,11,1,51,21,35,2,169,211,164,129,82,211,211,211,3,37,172,1,64,254,192,253,45,254,0,0,0,0,2,0,218,0,0,3,247,5,240,0,3,0,36,0,0,37,21,35,53,55,53,52,38,39,46,1,47,1,46,1,53,52,54,51,50, +22,23,21,46,1,35,34,6,21,20,22,31,1,30,1,29,1,3,3,203,6,6,6,8,39,47,88,90,72,223,184,103,193,94,97,179,79,108,131,51,57,90,90,56,254,254,254,147,123,52,60,21,25,53,47,86,86,137,76,159,194,56,57,188,67,70,110,89,49,94,53,89,86,130,101,154,0,1,1,178,0, +85,4,45,3,222,0,34,0,0,37,53,54,55,54,55,38,39,38,53,52,55,54,55,54,51,50,23,21,38,7,6,7,6,23,20,23,22,55,54,55,21,6,7,6,1,178,47,83,68,52,142,51,53,21,30,103,99,98,110,90,100,70,51,49,96,1,200,57,58,72,58,90,205,231,85,176,6,25,20,33,24,76,79,84,65, +75,118,63,61,22,185,31,2,1,26,48,112,115,50,14,15,19,35,185,60,80,90,255,255,1,0,0,0,3,208,7,131,16,38,4,93,0,0,16,7,4,132,0,0,1,194,255,255,1,189,0,0,3,20,7,253,16,38,4,93,0,0,16,7,4,133,0,0,1,134,255,255,0,76,254,12,4,51,4,181,16,38,4,121,0,0,16,7, +4,133,0,99,254,62,255,255,1,189,254,12,3,20,6,20,16,38,4,93,0,0,16,6,4,134,0,0,0,0,255,255,0,25,254,243,4,209,4,91,16,38,4,122,0,0,16,7,4,133,255,114,253,228,0,1,2,12,0,0,2,196,6,20,0,3,0,0,1,51,17,35,2,12,184,184,6,20,249,236,0,0,255,255,0,69,254,200, +4,176,2,27,16,39,13,17,2,44,254,200,16,6,13,32,0,0,255,255,0,222,255,198,3,243,4,26,16,39,13,18,1,113,3,132,16,6,4,120,0,0,255,255,0,69,255,236,4,176,3,32,16,39,13,18,1,184,2,138,16,6,13,32,0,0,255,255,0,69,255,236,4,176,4,26,16,39,13,19,1,164,2,138, +16,6,13,32,0,0,255,255,0,88,254,12,4,173,3,102,16,39,13,17,2,151,0,13,16,6,4,99,0,0,0,1,0,88,254,12,4,173,3,102,0,30,0,0,19,36,23,4,23,21,36,7,6,21,20,23,22,5,50,55,21,6,7,4,39,38,53,16,55,54,55,38,7,6,7,88,1,20,195,1,36,196,254,218,215,224,74,129,1, +19,193,212,150,250,254,148,169,131,212,96,137,101,159,135,95,3,39,64,1,1,53,154,13,180,188,247,137,94,163,1,118,184,98,1,2,196,152,222,1,2,223,101,52,3,22,19,41,0,255,255,0,88,254,12,4,173,4,176,16,39,13,17,1,202,4,26,16,6,4,99,0,0,0,1,0,232,255,218, +3,232,3,106,0,25,0,0,37,54,55,54,53,52,39,38,39,51,22,23,22,21,20,7,6,5,6,35,34,39,53,22,51,50,2,84,174,33,8,60,73,166,227,107,72,82,32,80,254,250,46,94,151,103,115,133,82,151,50,111,27,42,91,103,120,179,108,131,152,105,99,75,195,40,7,38,184,42,255,255, +0,232,255,218,3,232,4,200,16,39,13,17,2,28,4,50,16,6,4,101,0,0,0,1,255,204,254,8,4,68,2,34,0,17,0,0,37,54,53,52,39,51,22,21,20,7,2,5,4,5,53,32,55,36,3,133,10,53,184,50,8,41,254,181,254,239,254,21,1,188,220,0,255,154,58,72,126,136,118,132,82,62,254,181, +173,143,9,184,128,146,255,255,255,204,254,8,4,68,3,182,16,39,13,17,3,85,3,32,16,6,4,103,0,0,0,1,255,36,254,20,4,152,2,238,0,63,0,0,37,6,7,6,7,6,35,34,39,38,55,54,55,51,6,23,22,23,22,51,50,55,54,55,54,39,52,47,1,51,23,22,23,22,23,22,55,54,53,51,6,23,22, +51,50,25,1,51,17,20,7,6,7,6,35,34,39,38,39,6,7,6,7,6,1,140,9,29,38,60,71,114,95,101,117,18,19,61,164,88,6,7,33,47,47,54,50,34,26,24,2,16,42,160,18,16,22,48,40,46,46,36,164,4,38,31,43,104,164,62,33,85,22,78,66,24,65,25,31,69,51,73,48,60,168,94,121,77, +92,100,115,213,232,130,225,137,172,43,59,72,50,122,109,165,94,92,234,156,145,35,80,3,3,125,103,194,163,141,120,1,24,1,38,254,170,159,153,82,34,9,25,67,126,109,56,40,2,2,255,255,255,36,254,20,4,152,4,176,16,39,13,19,1,99,3,32,16,6,4,105,0,0,0,2,255,16, +254,20,4,192,2,143,0,12,0,61,0,0,37,51,50,55,54,53,52,39,38,35,34,7,6,7,54,55,54,51,50,23,22,21,20,7,6,43,1,34,39,38,53,20,7,6,7,6,35,34,39,38,53,52,55,51,6,21,20,23,22,55,54,55,54,53,52,39,38,39,51,20,23,22,2,72,128,141,73,106,40,36,64,71,103,76,196, +75,49,142,154,172,90,88,184,127,127,218,37,53,44,48,46,51,99,77,130,91,124,100,172,104,60,50,61,66,37,65,9,33,13,170,14,10,184,46,68,70,45,37,33,109,78,6,128,60,177,82,78,121,190,109,75,30,26,16,175,131,129,43,86,90,127,203,188,172,204,156,145,50,41, +3,4,59,106,136,104,62,212,72,15,55,40,0,0,0,255,255,255,16,254,20,4,192,3,77,16,39,13,17,1,79,2,183,16,6,4,107,0,0,0,2,0,10,0,0,4,164,6,20,0,12,0,31,0,0,37,51,50,55,54,53,52,39,38,35,34,7,6,19,33,35,53,51,17,51,17,54,55,54,51,50,23,22,21,20,7,6,2,44, +129,140,73,106,40,36,63,71,104,75,136,253,251,224,224,184,76,49,142,154,171,91,87,184,126,184,46,68,70,45,37,33,109,78,254,216,184,5,92,251,14,128,60,177,82,78,121,190,109,75,255,255,0,10,0,0,4,164,6,20,16,39,13,17,2,89,3,22,16,6,4,109,0,0,0,1,0,122, +254,12,4,183,4,42,0,42,0,0,5,22,33,50,55,21,6,35,32,39,38,53,52,55,54,55,38,39,38,53,52,55,54,51,21,34,7,6,21,20,23,22,51,50,55,54,55,21,4,7,6,21,20,1,88,119,1,83,193,212,150,250,254,91,166,98,87,113,77,51,47,88,204,124,252,195,116,93,48,45,46,40,41, +158,254,254,239,236,209,177,158,118,184,99,188,111,201,177,101,131,25,4,30,56,130,208,127,77,169,65,52,104,75,25,24,18,69,29,184,26,149,131,185,117,255,255,0,122,254,12,4,183,5,70,16,39,13,17,1,125,4,176,16,6,4,111,0,0,0,1,255,236,0,0,4,229,0,184,0,3, +0,0,35,53,33,21,20,4,249,184,184,0,255,255,255,182,255,164,4,140,4,204,16,39,13,17,2,252,4,54,16,6,13,40,0,0,255,255,0,31,254,125,4,116,5,20,16,39,13,18,2,83,4,126,16,6,13,33,0,0,0,2,0,8,255,201,4,159,6,20,0,33,0,61,0,0,1,21,6,7,6,21,20,23,22,23,22,21, +20,7,6,35,34,39,53,22,51,50,55,54,53,52,39,38,39,38,55,54,55,54,1,54,25,1,51,17,16,7,6,7,6,35,6,39,38,53,52,55,51,6,21,22,23,22,51,50,55,54,2,123,74,38,80,14,12,68,102,88,82,78,66,56,68,45,60,57,60,78,74,18,32,1,2,75,85,1,171,52,184,86,130,67,155,184, +173,163,217,16,184,14,2,152,121,87,127,62,119,4,76,82,4,14,30,33,28,18,16,10,15,88,110,42,39,11,88,10,26,26,30,38,17,16,28,47,46,81,38,43,252,209,56,1,18,3,177,252,79,254,154,92,136,25,55,2,57,76,184,75,53,58,44,93,45,35,27,52,0,0,0,1,0,67,254,200,4, +75,6,20,0,27,0,0,37,54,25,1,51,17,16,7,6,7,6,35,34,39,38,3,38,55,51,6,21,20,23,22,51,50,55,54,3,117,30,184,50,108,101,150,162,99,119,242,1,1,64,184,65,166,40,73,105,84,99,73,57,1,40,4,106,251,150,254,122,71,156,49,72,42,86,1,3,138,92,115,115,126,66,16, +34,41,0,2,0,130,254,20,4,84,2,243,0,17,0,46,0,0,1,22,51,50,55,54,53,52,39,38,39,38,35,34,7,6,21,20,7,38,7,6,21,17,35,17,52,55,54,51,38,53,52,55,54,51,50,23,22,23,22,21,20,7,6,35,6,2,88,122,76,44,21,53,6,21,59,40,46,59,27,68,110,50,75,25,200,120,65,90, +2,162,77,92,77,79,182,28,8,98,120,88,178,1,39,42,22,57,58,24,20,88,17,12,27,68,68,40,193,28,78,26,79,254,20,1,236,173,102,55,42,40,148,132,63,36,83,167,45,56,146,65,80,2,255,255,0,54,254,181,4,141,3,96,16,39,13,17,1,234,2,202,16,6,13,42,0,0,0,2,0,222, +255,198,3,243,2,222,0,15,0,31,0,0,1,34,7,6,23,22,23,22,51,50,55,54,53,52,39,38,39,50,23,22,21,6,7,6,35,34,39,38,53,52,55,54,2,14,66,33,26,1,1,55,57,57,91,93,75,66,123,152,198,182,141,1,147,165,132,96,81,167,37,84,2,42,87,69,123,82,44,44,57,46,85,77,65, +120,179,160,124,148,200,75,85,35,74,239,181,78,185,0,0,2,0,76,254,12,4,51,2,134,0,11,0,38,0,0,1,34,7,6,21,20,23,22,23,52,39,38,1,16,7,6,7,6,33,53,32,55,54,55,38,39,38,39,38,53,52,55,54,51,50,23,22,23,22,2,225,63,44,24,51,47,192,86,37,1,46,172,45,186, +190,254,106,1,115,161,224,49,118,45,139,51,116,211,57,62,89,72,131,24,17,1,196,57,33,36,55,43,40,4,184,59,25,254,244,254,218,174,46,84,86,184,76,104,139,3,7,24,43,98,137,217,90,24,51,91,142,102,0,1,0,25,254,243,4,209,3,28,0,53,0,0,37,6,7,6,35,34,39,36, +17,52,55,51,6,23,22,23,22,51,50,55,54,55,54,53,52,39,38,39,38,55,54,55,54,51,50,23,22,23,35,52,39,38,7,6,7,6,21,20,23,22,23,22,23,22,4,121,132,224,177,93,129,72,254,219,63,184,66,1,2,164,75,83,120,108,107,65,59,27,34,132,98,1,1,94,77,96,143,55,50,17, +184,19,27,39,20,24,35,125,91,55,31,1,1,12,195,48,38,26,104,1,5,117,113,131,99,147,45,20,35,35,78,71,34,46,42,51,58,44,131,150,61,50,73,66,137,61,25,34,4,2,20,30,57,41,44,32,103,58,94,77,255,255,0,25,254,12,4,209,3,28,16,39,13,18,1,114,254,12,16,6,4,122, +0,0,0,2,1,68,4,186,3,140,6,154,0,3,0,7,0,0,1,53,37,21,1,53,37,21,1,68,2,72,253,184,2,72,5,170,110,130,110,254,142,110,130,110,0,0,0,2,1,68,4,186,3,140,6,253,0,38,0,53,0,0,1,54,55,38,39,38,53,52,55,54,51,50,23,22,21,20,7,22,51,22,51,21,34,47,1,6,7,6,35, +34,39,38,53,51,20,23,22,51,50,55,54,55,54,53,52,38,35,34,7,6,21,20,23,22,2,116,36,22,33,23,108,68,29,63,73,39,56,13,19,14,19,19,46,20,52,26,76,84,94,115,55,16,90,12,36,48,56,158,4,2,10,34,20,24,10,18,44,20,5,100,36,42,7,13,57,94,87,52,21,39,54,79,39, +38,1,1,110,2,5,61,78,86,154,41,113,97,26,75,238,7,7,21,24,34,28,9,13,28,37,18,8,0,0,0,0,2,1,68,254,22,3,140,255,246,0,3,0,7,0,0,1,53,37,21,37,53,37,21,1,68,2,72,253,184,2,72,254,22,110,130,110,110,110,130,110,0,0,0,0,1,1,68,4,186,3,140,5,170,0,3,0,0, +1,53,37,21,1,68,2,72,4,186,110,130,110,0,0,2,1,68,4,185,3,140,6,253,0,31,0,47,0,0,1,38,39,38,53,52,55,54,51,50,23,22,21,20,7,22,51,22,51,21,34,39,38,39,6,7,6,35,53,50,55,54,55,54,55,54,53,52,39,38,35,34,7,6,21,20,23,22,2,146,9,19,108,68,29,63,73,39,56, +15,17,18,19,19,34,32,31,27,43,69,201,147,153,139,22,86,4,2,10,18,16,20,24,10,18,44,20,5,186,2,10,56,95,87,52,21,39,54,79,32,45,1,1,110,2,2,3,61,42,123,110,109,18,112,7,7,21,24,34,14,14,9,13,28,37,18,8,0,0,1,1,68,254,232,3,140,255,216,0,3,0,0,1,53,37, +21,1,68,2,72,254,232,110,130,110,0,0,1,1,48,4,203,3,160,6,244,0,40,0,0,1,6,7,6,7,6,39,38,53,52,55,51,6,23,22,23,22,55,54,55,54,53,51,20,23,22,55,54,53,52,39,51,22,7,6,7,6,7,6,39,38,2,120,15,33,57,69,79,41,34,16,97,12,1,3,22,19,50,61,4,2,96,3,14,75,71, +13,103,15,3,3,24,38,90,71,31,27,5,132,77,39,68,1,2,65,50,111,109,98,125,56,84,34,28,23,26,168,82,89,36,54,197,2,1,173,115,57,73,116,133,54,88,11,9,33,30,0,0,0,2,1,86,4,225,3,122,7,6,0,9,0,19,0,0,1,52,38,34,6,21,20,22,50,62,1,20,6,35,34,38,52,54,51,50, +3,0,88,128,88,88,128,88,122,158,116,114,160,160,114,116,5,244,63,88,87,64,65,87,88,179,230,160,160,230,159,0,0,1,1,0,4,185,3,208,5,193,0,18,0,0,1,55,22,23,22,51,50,55,54,55,21,6,7,6,35,34,38,39,7,1,0,160,103,67,42,54,58,42,107,87,90,90,66,54,34,152,68, +166,5,54,123,83,21,13,16,41,76,125,64,29,22,34,70,128,255,255,1,189,4,191,3,20,6,119,16,6,4,150,0,141,255,255,1,189,254,12,3,20,255,196,16,7,4,150,0,0,248,218,0,0,0,1,1,92,4,238,3,118,6,52,0,6,0,0,1,3,51,23,55,51,3,2,30,194,138,130,130,140,196,4,238, +1,70,195,195,254,186,0,0,0,0,1,1,250,1,194,2,214,2,188,0,3,0,0,1,51,21,35,1,250,220,220,2,188,250,0,0,0,0,1,1,150,0,0,3,60,5,20,0,9,0,0,33,35,16,39,2,3,51,18,19,22,3,60,180,38,49,155,196,121,73,32,1,169,220,1,33,1,110,254,221,254,148,155,0,0,0,1,0,154, +0,0,4,56,5,20,0,24,0,0,1,22,23,22,17,35,16,39,2,3,51,22,23,22,51,22,55,54,55,51,6,7,2,35,34,1,237,28,23,32,180,38,49,155,198,67,3,82,180,122,54,32,8,180,8,42,98,244,111,3,97,106,114,155,254,22,1,169,220,1,33,1,110,155,5,152,2,149,85,80,121,109,254,250, +0,1,0,134,0,0,4,76,5,20,0,37,0,0,1,22,23,22,17,35,16,39,2,3,51,22,23,22,55,54,55,54,53,51,20,23,22,23,22,55,54,53,51,16,7,6,35,34,39,6,7,6,1,228,24,16,32,180,38,49,155,196,47,40,19,48,72,8,6,180,14,21,47,60,14,14,180,40,70,156,132,33,51,52,46,3,53,87, +89,190,254,57,1,169,220,1,33,1,110,114,124,62,8,12,64,50,166,222,25,37,2,2,44,42,202,254,207,59,108,62,51,12,10,0,0,1,0,236,255,236,3,228,5,32,0,42,0,0,1,21,6,7,6,21,20,23,22,23,21,34,7,6,21,20,23,22,23,50,55,54,55,21,6,7,6,35,34,39,38,53,52,55,54,55, +38,39,38,39,38,55,54,3,96,121,103,136,92,78,78,89,135,112,48,60,74,98,88,126,86,72,124,101,101,150,112,100,108,64,88,72,44,55,1,1,225,113,5,32,168,17,52,67,64,35,57,48,4,164,76,64,114,82,60,74,1,23,33,43,196,37,28,23,125,112,165,134,128,76,24,32,48,58, +63,150,128,63,0,2,0,202,255,236,4,8,5,36,0,13,0,28,0,0,0,34,7,6,7,6,23,22,32,55,54,39,38,39,3,22,19,22,21,16,7,6,32,39,38,17,52,55,18,2,171,133,86,79,3,5,71,41,0,255,40,72,4,4,78,154,191,135,90,86,104,254,61,105,84,90,135,4,104,212,192,174,199,115,66, +66,115,199,174,192,1,144,1,254,161,235,179,254,203,117,144,144,117,1,53,179,235,1,97,0,0,0,0,1,0,154,0,0,4,55,5,20,0,17,0,0,1,16,19,18,19,35,2,3,2,39,6,35,34,39,53,22,51,50,3,147,37,29,98,196,85,31,28,2,96,142,178,167,180,165,210,5,20,254,220,254,159, +254,235,254,134,1,68,1,75,1,42,145,28,50,180,50,0,0,0,1,0,126,0,0,4,82,5,20,0,18,0,0,33,38,3,2,39,51,18,19,22,23,54,55,18,19,51,2,3,2,7,2,14,16,98,160,126,196,154,90,48,2,2,48,90,154,196,164,120,86,30,246,1,58,1,254,230,254,202,254,197,168,11,11,168, +1,59,1,54,254,211,254,73,254,202,250,0,0,0,1,0,126,0,0,4,82,5,20,0,18,0,0,1,51,22,19,18,19,35,2,3,38,39,6,7,2,3,35,54,19,18,2,14,180,30,86,120,164,196,154,90,48,2,2,48,90,154,196,126,160,98,5,20,250,254,202,254,73,254,211,1,54,1,59,168,11,11,168,254, +197,254,202,230,1,254,1,58,0,0,2,0,162,0,0,4,48,5,30,0,20,0,35,0,0,1,38,39,38,39,38,39,38,55,54,23,22,23,22,23,22,23,18,19,35,2,3,39,38,39,38,35,34,7,6,23,22,23,22,23,22,2,252,205,61,165,66,103,2,4,99,126,146,154,92,128,14,10,18,36,91,196,92,36,7,10, +34,56,107,78,58,58,2,1,59,33,77,79,2,85,3,15,41,65,101,123,142,98,126,1,1,84,118,167,135,150,254,205,254,164,1,156,1,110,87,108,60,97,55,54,71,57,54,31,13,14,0,0,3,0,200,0,0,4,10,5,20,0,3,0,7,0,11,0,0,37,51,21,35,1,51,21,35,37,51,1,35,3,70,180,180,253, +144,180,180,2,148,160,253,94,160,250,250,5,20,250,250,250,236,0,1,1,54,255,31,3,155,2,139,0,17,0,0,5,54,55,54,55,54,53,52,39,51,22,21,20,7,6,7,6,7,1,54,168,113,107,47,25,21,150,24,75,79,165,106,188,70,5,113,109,143,80,79,96,96,78,111,170,160,166,113, +72,6,0,1,1,214,3,254,2,251,5,213,0,5,0,0,1,51,21,3,35,19,2,40,211,164,129,82,5,213,152,254,193,1,63,0,0,0,0,1,0,146,0,206,4,64,4,76,0,9,0,0,19,33,27,1,33,5,19,37,5,19,146,1,103,111,113,1,103,254,221,112,254,219,254,221,111,2,247,1,85,254,171,212,254, +171,211,211,1,85,0,1,1,189,5,50,3,20,6,234,0,24,0,0,1,55,38,39,38,55,54,55,54,23,22,23,21,38,35,34,7,6,21,20,23,22,55,21,5,1,189,78,44,16,17,1,2,54,56,94,61,53,51,63,66,17,29,94,33,120,254,169,5,150,18,20,36,37,45,95,44,46,1,1,32,100,33,18,32,26,77,27, +10,29,102,77,0,0,255,255,0,69,255,236,4,176,4,153,16,39,4,84,0,42,253,168,16,6,13,32,0,0,255,255,0,69,255,236,4,176,4,26,16,39,13,26,2,22,3,132,16,6,13,32,0,0,255,255,0,69,254,12,4,176,2,27,16,39,13,26,2,16,255,6,16,6,13,32,0,0,255,255,0,69,254,12,4, +176,2,27,16,39,13,25,1,158,255,6,16,6,13,32,0,0,255,255,0,69,255,236,4,176,4,26,16,39,13,27,1,164,3,132,16,6,13,32,0,0,255,255,0,69,254,12,4,176,2,27,16,39,13,27,1,158,255,6,16,6,13,32,0,0,255,255,0,88,254,12,4,173,3,102,16,39,13,18,2,42,0,81,16,6,4, +99,0,0,255,255,0,88,254,12,4,173,3,102,16,39,13,26,2,203,0,175,16,6,4,99,0,0,255,255,0,88,254,12,4,173,3,102,16,39,13,25,2,106,0,150,16,6,4,99,0,0,255,255,0,88,254,12,4,173,3,102,16,39,13,27,2,98,0,175,16,6,4,99,0,0,255,255,255,204,254,8,4,208,4,168, +16,38,4,103,0,0,16,7,4,84,1,98,253,183,255,255,255,204,254,8,4,101,4,113,16,39,13,19,2,213,2,225,16,6,4,103,0,0,255,255,255,182,255,164,4,140,5,153,16,39,13,19,2,112,4,9,16,6,13,40,0,0,0,1,0,10,255,167,5,93,6,20,0,42,0,0,37,50,54,55,54,53,52,47,1,38, +53,52,55,54,55,1,21,1,6,21,20,31,1,22,21,20,7,6,7,6,35,34,39,36,17,52,55,51,6,21,20,23,22,2,38,162,218,54,52,95,183,62,18,46,86,2,15,254,104,71,32,148,142,104,82,164,99,207,112,108,254,182,63,184,65,203,79,88,106,60,57,85,57,105,202,68,71,84,31,79,65, +1,142,209,254,194,55,46,63,35,162,155,111,157,117,92,78,47,32,98,1,11,138,92,94,136,120,72,28,0,0,0,255,255,0,10,255,167,5,97,7,56,16,39,13,28,2,170,0,0,16,6,4,164,0,0,0,3,0,0,255,189,4,147,3,229,0,38,0,54,0,70,0,0,40,1,39,38,53,52,55,51,6,21,20,23,22, +51,50,55,38,39,38,53,52,55,54,23,38,39,53,22,23,4,23,22,21,20,7,6,35,34,39,55,54,55,54,53,52,39,38,35,34,7,6,21,20,23,22,37,22,21,20,7,6,7,22,51,50,55,54,53,52,39,38,1,221,254,220,67,118,16,184,14,30,45,40,59,71,45,15,18,45,48,77,44,81,219,220,1,5,59, +14,40,74,175,131,154,21,36,34,39,15,22,58,65,23,22,7,21,1,71,6,98,12,17,52,49,126,16,7,33,29,36,64,128,75,53,58,44,43,11,16,11,105,69,78,64,84,83,90,9,39,14,185,67,180,214,217,52,57,103,61,113,108,228,27,64,72,61,46,37,52,45,43,35,30,37,118,188,37,39, +138,114,14,19,46,67,30,33,60,78,69,0,255,255,0,25,254,243,4,209,3,28,16,6,4,122,0,0,255,255,1,250,1,194,2,214,2,188,16,6,4,136,0,0,255,255,1,150,0,0,3,60,5,20,16,6,4,137,0,0,255,255,0,154,0,0,4,56,5,20,16,6,4,138,0,0,255,255,0,134,0,0,4,76,5,20,16,6, +4,139,0,0,0,1,0,175,0,0,4,34,5,37,0,39,0,0,1,38,53,52,55,54,51,50,23,21,38,7,6,7,6,21,20,23,22,55,54,55,21,6,35,34,39,22,23,22,17,35,16,39,2,3,51,22,23,22,2,37,4,88,92,108,84,88,92,68,56,30,31,25,47,48,69,141,195,61,141,146,27,23,32,180,37,49,156,199, +66,3,27,4,20,15,19,120,58,61,25,156,36,2,1,33,34,21,52,21,39,2,2,17,180,26,81,106,114,155,254,22,1,169,220,1,33,1,110,155,5,56,0,0,0,2,0,172,255,245,4,36,5,36,0,19,0,39,0,0,1,22,51,50,55,54,53,52,39,38,34,7,6,21,20,23,22,51,50,55,23,6,39,38,39,38,53, +16,55,18,51,50,19,22,19,22,7,6,7,6,2,194,45,50,34,18,27,87,90,174,91,86,27,15,37,51,44,90,40,145,160,46,53,95,179,170,162,187,94,1,1,53,51,156,144,1,90,161,74,107,86,215,216,224,224,213,218,60,133,74,161,208,151,2,2,156,181,124,1,38,196,1,118,254,138, +187,254,209,141,164,157,1,2,0,0,0,0,1,1,8,0,0,3,200,5,31,0,32,0,0,33,18,55,54,55,34,39,38,53,52,55,54,55,54,23,21,38,35,34,7,6,21,20,23,22,51,50,55,21,6,7,6,7,1,8,66,110,68,100,78,46,134,98,112,140,121,87,86,116,62,48,66,55,44,103,140,96,225,111,134, +54,0,255,181,111,85,37,109,151,175,96,109,2,2,33,180,51,47,65,98,77,51,41,41,180,73,152,183,225,0,255,255,0,126,0,0,4,82,5,20,16,6,4,143,0,0,255,255,0,126,0,0,4,82,5,20,16,6,4,144,0,0,255,255,0,162,0,0,4,48,5,30,16,6,4,145,0,0,0,5,0,184,254,211,4,96, +6,20,0,3,0,7,0,30,0,39,0,48,0,0,1,17,51,17,3,17,51,25,1,51,21,22,23,22,21,20,6,7,30,1,21,20,7,6,7,17,35,17,33,17,33,19,54,55,54,53,52,39,38,39,53,54,55,54,53,52,39,38,39,1,124,180,180,180,100,184,106,119,126,126,142,161,128,116,216,100,254,136,1,120, +100,131,61,72,76,64,124,99,51,63,62,49,102,4,137,254,118,1,138,253,231,254,33,1,223,3,164,251,9,76,86,160,120,138,17,19,181,140,179,90,81,8,254,210,1,45,5,26,251,120,7,46,54,123,128,60,50,8,147,8,39,49,109,99,44,35,7,0,0,3,0,62,255,235,4,100,4,123,0, +7,0,15,0,42,0,62,64,13,35,6,37,10,2,27,20,14,6,22,6,16,43,16,220,236,204,204,220,60,204,204,47,236,49,0,64,7,0,22,4,18,153,37,43,16,60,244,204,220,204,64,9,12,25,8,40,140,29,33,190,44,16,252,60,236,204,220,204,48,37,38,21,20,55,54,39,38,3,38,21,20,55, +54,39,38,19,20,35,34,53,52,55,17,6,35,34,53,52,51,50,23,54,51,32,25,1,35,17,52,35,34,7,1,20,63,63,66,1,1,76,63,63,66,1,1,162,198,230,244,21,21,202,202,145,44,76,189,1,150,184,226,137,87,244,2,66,65,1,1,63,62,3,5,2,66,65,1,1,63,62,252,195,205,201,202, +6,1,112,8,208,191,81,81,254,190,252,199,3,57,170,142,0,2,0,108,255,221,4,174,4,140,0,3,0,44,0,0,0,34,20,50,7,34,53,52,55,54,55,36,19,22,5,7,4,23,22,51,50,54,51,50,23,7,38,35,34,6,35,32,39,52,37,55,54,53,52,5,6,7,22,23,20,1,130,128,128,68,210,188,187, +151,1,229,1,2,254,152,182,254,227,3,5,231,74,214,80,158,138,134,105,63,51,204,107,254,93,1,1,180,178,214,254,200,75,77,63,1,3,111,128,148,228,137,97,98,1,2,254,169,237,117,59,92,83,102,142,213,97,145,127,249,198,142,58,70,130,189,3,1,55,56,85,216,0,0, +0,3,0,121,255,236,4,80,4,140,0,7,0,17,0,56,0,0,1,22,51,50,55,38,39,34,19,22,39,38,35,34,23,20,21,22,37,52,55,38,55,54,36,23,4,18,25,1,35,17,16,38,7,14,1,23,54,55,32,7,20,35,34,39,6,23,22,23,54,51,50,21,20,7,4,1,89,54,5,23,48,73,1,18,127,54,2,3,49,54, +2,1,254,174,42,44,3,6,1,11,229,1,33,191,184,127,169,177,155,3,42,58,1,5,1,250,57,20,31,3,2,20,23,171,204,204,254,117,2,96,20,18,17,1,254,16,1,48,39,34,1,3,47,220,127,128,54,79,211,217,1,1,254,224,254,214,253,191,2,65,1,1,183,3,3,184,75,18,1,165,165,11, +37,91,57,46,141,200,181,1,1,0,0,0,0,2,0,246,254,24,3,219,4,140,0,25,0,33,0,0,19,52,54,51,32,25,1,16,6,35,34,38,39,55,22,51,50,53,17,16,35,22,21,6,39,38,19,38,23,6,55,22,39,54,247,162,221,1,101,155,204,214,116,13,189,33,121,175,130,2,6,215,209,215,67, +3,2,66,66,2,1,3,166,113,117,253,244,253,143,254,249,240,208,141,10,209,243,2,223,1,104,21,33,207,1,1,1,9,1,65,67,3,2,66,66,0,0,2,0,124,255,255,4,85,4,154,0,11,0,41,0,0,1,34,6,21,20,22,51,50,54,53,52,38,3,50,23,22,25,1,7,19,52,39,20,39,38,53,52,51,50, +23,16,5,6,7,6,29,1,35,53,52,55,54,2,110,36,28,32,32,37,27,32,42,250,124,123,184,1,101,200,217,218,244,54,254,196,207,76,17,184,30,106,2,96,32,32,37,27,34,30,37,27,2,58,121,120,254,217,253,126,1,1,41,142,82,166,1,2,183,192,104,1,149,5,4,134,30,134,75, +75,170,62,220,0,2,0,97,254,25,4,201,4,130,0,11,0,57,0,0,1,34,6,21,20,22,51,50,54,53,52,38,3,38,53,52,53,54,55,54,55,36,19,22,13,1,6,23,22,51,50,55,54,51,50,21,20,19,48,7,2,17,6,33,32,53,52,45,1,54,53,52,5,6,7,22,23,6,1,54,36,28,32,32,37,27,32,35,210, +2,229,118,202,1,201,2,1,254,138,254,251,169,5,4,199,179,93,35,120,151,134,144,176,46,254,164,254,127,1,62,1,1,229,254,226,114,62,62,1,36,3,111,32,32,37,27,34,30,37,27,254,236,16,209,2,1,133,125,64,1,2,254,188,214,126,89,57,112,101,183,68,216,243,254, +181,81,1,99,1,70,211,248,226,108,87,78,110,169,3,1,45,55,86,188,0,2,0,115,255,239,4,92,4,149,0,11,0,44,0,0,1,50,54,53,52,38,39,38,6,21,20,22,3,20,33,32,25,1,51,17,16,37,36,17,52,53,54,55,38,55,18,5,22,21,20,7,6,39,22,23,22,55,21,7,6,1,215,36,28,33,31, +37,27,32,130,1,47,1,64,184,254,8,254,15,3,162,166,1,1,1,108,180,192,126,46,2,90,65,144,141,147,3,164,32,32,36,27,1,1,33,32,36,28,253,140,174,1,184,2,63,253,193,253,180,1,1,1,61,2,1,145,81,109,234,1,46,2,1,176,186,2,1,117,189,71,52,12,161,23,24,0,0,0, +2,0,123,255,227,4,86,4,123,0,7,0,28,0,44,64,9,27,6,8,6,16,2,21,6,14,47,252,204,220,204,47,236,49,0,64,12,11,140,24,190,29,0,14,4,18,153,28,29,16,60,244,204,220,204,16,252,252,48,37,34,21,20,51,50,53,52,5,17,52,5,4,21,17,36,23,22,35,34,53,17,52,36,55, +54,4,21,17,1,102,64,64,64,1,248,254,202,254,203,1,24,1,1,231,235,1,19,218,197,1,41,235,64,64,64,64,235,3,31,201,3,3,195,254,80,27,223,200,200,2,142,199,121,2,2,120,204,252,199,0,2,0,149,255,226,4,111,4,161,0,11,0,42,0,0,37,34,6,21,20,22,51,50,54,53,52, +38,19,34,2,35,34,7,3,32,21,20,35,34,53,17,16,51,50,18,51,50,18,55,50,25,1,35,17,52,35,34,2,1,128,36,28,32,32,37,27,32,228,122,119,15,54,1,1,1,25,213,251,242,131,94,34,36,74,133,242,184,55,22,102,241,32,32,37,27,34,30,37,27,1,250,1,38,225,254,80,196,218, +210,2,150,1,87,254,224,1,31,1,254,169,252,182,3,48,219,254,224,0,3,0,26,254,20,4,62,4,123,0,3,0,7,0,35,0,0,36,34,20,50,0,34,20,50,19,50,23,22,35,34,53,17,6,35,38,53,54,55,54,23,54,51,32,22,21,17,35,17,52,35,34,7,2,38,128,128,254,237,128,128,166,241,2, +2,218,211,33,31,167,1,179,145,55,121,139,1,6,158,184,244,123,94,220,128,3,166,128,253,221,185,195,227,2,73,7,2,190,178,1,1,101,100,213,109,250,219,5,37,163,139,0,2,0,106,255,227,4,104,4,123,0,7,0,39,0,62,64,7,6,12,2,8,36,6,15,47,252,60,204,220,204,64, +7,20,6,32,24,6,26,41,16,220,236,220,236,49,0,64,6,17,140,34,153,26,41,16,60,244,236,64,9,4,38,0,29,140,22,10,190,41,16,252,60,236,204,220,204,48,1,38,23,6,55,22,39,54,5,52,51,50,21,20,6,21,20,51,50,53,17,52,23,4,21,17,35,17,52,7,6,21,3,2,37,36,17,16, +55,34,1,54,67,3,2,66,67,3,2,254,244,202,216,254,170,178,252,1,0,164,98,82,1,1,254,172,254,176,216,214,4,18,2,66,67,3,1,65,67,75,177,173,202,224,212,216,188,2,74,254,1,1,251,252,129,3,127,106,3,3,101,253,183,254,173,1,1,1,104,1,48,154,0,0,0,2,0,75,255, +227,4,84,4,140,0,5,0,32,0,0,0,50,52,35,34,7,3,53,51,50,54,53,17,36,53,52,55,54,21,17,22,55,54,53,17,51,17,16,33,34,39,6,35,1,3,128,64,62,2,184,122,93,85,254,232,226,238,93,120,152,184,254,180,174,84,114,217,3,115,128,64,252,48,143,101,156,1,103,8,204, +221,1,1,219,253,117,169,1,1,177,3,47,252,209,254,178,115,115,0,2,0,125,255,239,4,84,4,124,0,3,0,25,0,0,0,34,20,50,1,52,55,38,55,54,23,22,7,6,0,21,22,37,32,25,1,51,17,16,37,36,1,169,128,128,254,212,182,183,1,1,229,237,1,1,254,236,1,1,37,1,60,184,254,12, +254,29,3,238,128,253,210,218,196,38,182,196,2,2,188,151,254,209,168,204,1,1,39,2,180,253,76,254,66,1,1,0,0,0,0,2,0,125,255,239,4,84,6,20,0,3,0,25,0,0,0,34,20,50,1,52,55,38,55,54,23,22,7,6,0,21,22,33,32,25,1,51,17,16,37,36,1,169,128,128,254,212,182,183, +1,1,229,237,1,1,254,236,1,1,37,1,60,184,254,12,254,29,3,238,128,253,210,218,196,38,182,196,2,2,188,151,254,209,168,203,1,39,4,104,251,152,254,66,1,1,0,3,0,99,255,239,4,245,5,27,0,11,0,23,0,74,0,0,1,34,6,21,20,22,51,50,54,53,52,38,5,34,6,21,20,22,51,50, +54,53,52,38,1,43,1,38,39,6,35,34,39,38,53,17,52,51,50,21,6,39,16,21,20,51,50,53,17,51,17,20,55,54,53,17,38,55,52,23,22,23,54,53,38,39,55,22,23,22,7,19,20,7,6,3,132,36,28,32,32,37,27,32,253,146,36,28,32,32,38,26,32,1,224,2,2,99,103,101,133,126,80,76,210, +216,1,241,102,138,184,114,116,243,1,208,179,27,30,1,74,119,84,1,3,152,2,92,85,3,250,32,32,38,26,34,30,36,28,1,32,32,37,27,34,30,37,27,251,246,1,73,74,84,79,154,2,98,223,197,199,23,254,111,59,132,132,1,52,254,203,139,5,5,130,1,204,8,168,209,1,1,152,22, +80,54,65,94,103,91,195,111,254,6,164,80,73,0,0,2,0,99,255,239,4,98,6,20,0,36,0,48,0,0,1,20,7,6,43,2,38,39,6,35,34,39,38,53,17,52,51,50,21,6,39,16,21,20,51,50,53,17,51,17,20,55,54,53,17,51,1,34,6,21,20,22,51,50,54,53,52,38,4,98,92,85,123,2,2,99,103,101, +133,126,80,76,210,216,1,241,102,138,184,114,116,184,252,212,36,28,32,32,38,26,32,1,44,164,80,73,1,73,74,84,79,154,2,98,223,197,199,23,254,111,59,132,132,1,52,254,203,139,5,5,130,4,232,253,229,32,32,37,27,34,30,37,27,0,0,2,0,101,255,239,4,108,4,125,0, +11,0,44,0,0,1,34,6,21,20,22,51,50,54,53,52,38,19,50,53,17,51,17,6,55,54,53,17,51,17,16,37,38,39,6,35,32,17,52,55,38,55,54,23,22,7,6,0,23,20,1,98,36,28,32,32,36,28,32,48,110,184,1,117,104,184,254,224,105,103,101,143,254,222,152,138,2,2,228,237,1,2,254, +214,2,3,210,32,32,37,27,34,30,37,27,252,179,167,1,52,254,203,174,5,5,165,3,47,252,209,254,192,3,1,73,74,1,61,240,166,37,158,249,1,1,219,143,254,170,144,167,0,0,0,2,0,101,255,239,4,108,6,20,0,11,0,44,0,0,1,34,6,21,20,22,51,50,54,53,52,38,19,50,53,17,51, +17,6,55,54,53,17,51,17,16,37,38,39,6,35,32,17,52,55,38,55,54,23,22,7,6,0,23,20,1,98,36,28,32,32,36,28,32,48,110,184,1,117,104,184,254,224,105,103,101,143,254,222,152,138,2,2,228,237,1,2,254,214,2,3,210,32,32,37,27,34,30,37,27,252,179,167,1,52,254,203, +175,6,5,165,4,232,251,24,254,192,3,1,73,74,1,61,240,166,37,158,249,1,1,219,143,254,170,144,167,0,0,0,1,0,16,255,227,4,96,4,96,0,23,0,0,1,51,17,16,51,50,25,1,51,17,16,33,34,39,6,35,34,53,52,51,50,7,50,53,1,99,184,189,208,184,254,120,240,41,51,182,198, +156,144,2,41,4,96,253,44,254,237,1,19,2,212,252,197,254,190,56,56,156,150,123,139,0,0,2,0,115,255,239,4,92,6,20,0,11,0,44,0,0,1,50,54,53,52,38,39,38,6,21,20,22,3,20,33,32,25,1,51,17,16,37,36,17,52,53,54,55,38,55,18,5,22,21,20,7,6,39,22,23,22,55,21,7, +6,1,215,36,28,33,31,37,27,32,130,1,47,1,64,184,254,8,254,15,3,162,166,1,1,1,108,180,192,126,46,2,90,65,144,141,147,3,164,32,32,36,27,1,1,33,32,36,28,253,140,174,1,184,3,218,252,38,253,180,1,1,1,61,2,1,145,81,109,234,1,46,2,1,176,186,2,1,117,189,71,52, +12,161,23,24,0,0,0,2,0,100,255,239,4,109,4,140,0,11,0,43,0,0,1,34,6,21,20,22,51,50,54,53,52,38,5,38,33,32,19,18,33,32,23,7,38,7,4,23,22,5,4,3,2,37,36,38,55,54,23,22,21,20,7,22,55,54,1,61,36,28,32,32,36,28,32,2,87,1,254,189,253,243,1,1,2,21,1,54,184,116, +177,211,254,169,3,5,1,109,1,225,3,2,254,50,254,167,223,1,1,210,224,22,74,142,219,1,88,32,32,36,28,32,32,36,28,16,232,1,56,1,36,220,123,188,1,2,138,158,1,1,254,144,254,154,1,1,178,123,204,1,1,209,78,20,38,1,2,0,0,2,0,97,255,239,4,112,4,140,0,11,0,46,0, +0,37,34,6,21,20,22,51,50,54,53,52,38,1,4,25,1,20,37,38,2,39,38,7,22,7,6,39,38,55,18,33,50,18,55,54,53,17,16,33,34,7,6,7,39,54,55,54,1,70,37,27,32,32,36,28,32,1,8,2,2,254,244,232,87,139,68,12,227,2,2,207,250,1,1,1,78,232,98,102,80,254,198,229,39,26,2, +183,6,17,71,248,33,31,36,28,32,32,36,27,3,149,1,254,137,253,212,250,1,1,1,221,2,1,84,1,183,214,1,1,235,1,137,254,30,2,2,174,1,168,1,24,114,74,99,20,111,60,249,0,0,0,2,0,111,255,229,4,98,4,123,0,5,0,31,0,0,1,34,20,51,50,54,1,18,33,32,25,1,16,37,38,36, +39,52,23,50,23,22,7,22,51,32,53,17,52,33,32,7,1,80,64,64,60,8,254,244,41,1,189,1,244,254,34,240,254,220,1,229,217,4,1,70,25,127,1,30,254,204,254,233,24,1,84,128,128,1,206,1,89,254,215,253,184,254,217,2,1,156,143,211,1,215,61,73,8,216,1,196,204,213,0, +0,0,3,0,98,255,239,5,34,5,156,0,11,0,50,0,58,0,0,37,34,6,21,20,22,51,50,54,53,52,38,37,17,6,33,36,55,54,33,32,23,54,39,38,39,55,22,23,22,7,17,20,37,38,2,39,38,7,22,7,6,39,38,55,18,33,50,18,55,54,1,32,53,52,33,32,21,20,1,72,38,26,32,32,36,28,32,2,74,70, +254,234,254,10,2,2,1,242,1,142,114,28,2,11,99,158,128,2,2,178,254,244,232,88,138,68,12,226,2,2,206,251,1,2,1,78,232,98,102,80,254,164,1,116,254,140,254,182,248,33,31,36,28,32,32,36,27,61,1,153,14,1,252,233,154,49,18,84,132,118,174,160,146,151,253,195, +250,1,1,1,221,2,1,84,1,183,214,1,1,235,1,137,254,30,2,2,2,209,69,109,77,100,0,0,3,0,20,255,232,4,189,4,153,0,6,0,13,0,54,0,0,0,34,21,6,51,50,55,36,34,21,6,51,50,55,3,36,17,16,55,38,55,54,23,22,7,14,1,17,20,51,54,53,17,6,43,1,38,55,54,51,50,23,54,55,54, +25,1,35,17,52,35,34,7,19,16,1,26,128,1,65,63,1,1,145,128,1,65,63,1,238,254,96,130,140,1,1,198,190,1,1,186,223,225,20,29,2,185,1,1,166,162,53,64,86,247,184,67,63,47,1,4,26,64,64,64,76,64,64,64,252,2,1,1,69,1,62,169,47,153,181,1,1,178,125,204,254,159,182, +1,181,2,8,9,6,183,169,99,98,1,4,254,186,252,169,3,87,157,90,253,154,254,179,0,0,0,3,0,119,255,239,4,106,4,140,0,11,0,37,0,45,0,0,1,34,6,21,20,22,51,50,54,53,52,38,55,36,17,16,5,4,25,1,20,37,38,39,38,55,54,23,22,21,20,7,22,51,32,53,17,6,19,52,5,4,7,6, +5,4,1,92,36,28,32,32,37,27,32,244,254,7,1,249,1,250,254,10,202,170,134,1,1,220,237,61,65,56,1,41,83,85,254,196,254,192,1,1,1,66,1,60,1,83,32,32,37,27,34,30,36,28,208,1,1,51,1,54,1,1,254,209,253,140,251,2,1,72,57,170,215,1,1,216,71,41,35,175,1,36,54,1, +55,156,1,1,154,159,1,1,0,0,0,2,0,85,255,239,4,218,4,216,0,11,0,54,0,0,1,34,6,21,20,22,51,50,54,53,52,38,1,36,39,38,37,36,55,54,33,50,23,22,51,50,19,23,2,7,6,39,38,35,34,23,22,5,4,3,2,37,36,39,38,55,54,23,22,21,20,21,6,7,22,1,50,36,28,32,32,37,27,32,1, +0,1,84,1,1,254,192,253,254,3,3,1,158,136,92,111,69,104,64,148,77,243,135,113,75,85,210,5,5,1,80,1,230,1,1,253,240,254,236,136,110,1,1,224,215,1,94,153,1,139,32,32,37,27,34,30,37,27,254,249,2,254,195,43,68,231,252,89,108,1,4,48,254,149,1,1,121,80,94,100, +54,81,254,193,254,113,2,1,116,94,125,223,1,1,214,2,1,93,70,28,0,0,0,0,2,0,48,255,38,4,169,4,161,0,3,0,36,0,0,0,34,20,50,3,39,1,0,39,38,15,1,6,39,36,3,2,33,32,7,6,39,38,53,34,21,20,51,50,63,1,54,23,22,21,20,1,2,42,128,128,202,129,2,43,1,24,61,25,120,165, +130,215,254,226,7,9,1,136,1,15,1,1,211,212,35,101,115,90,140,175,104,224,254,225,4,13,128,251,153,134,2,78,1,41,61,25,137,187,147,1,1,1,109,1,144,206,216,3,4,205,205,195,100,157,196,2,5,189,157,254,207,255,255,0,91,255,229,4,100,4,128,16,39,4,208,4,209, +250,201,16,7,4,208,4,209,253,117,0,0,0,2,251,138,5,28,255,147,7,11,0,19,0,26,0,0,3,2,33,32,38,55,54,23,50,7,6,7,22,51,36,53,52,39,55,22,4,52,7,34,21,6,23,109,2,254,5,254,182,195,1,1,229,241,3,1,35,33,65,1,28,86,138,168,253,28,66,56,1,63,6,29,254,255, +168,107,217,1,216,80,36,4,1,85,46,70,138,143,140,126,1,62,61,1,0,0,0,2,0,157,0,0,4,33,4,123,0,16,0,22,0,0,1,32,25,1,35,17,16,35,34,7,50,21,20,35,34,53,16,18,20,51,50,52,35,2,106,1,183,184,255,164,61,218,229,225,166,59,67,62,4,123,254,106,253,27,2,203, +1,25,86,193,199,199,1,174,254,137,110,110,0,0,255,255,252,197,0,0,4,33,6,114,16,38,4,209,0,0,16,7,4,224,251,47,0,0,0,1,0,83,4,236,4,126,7,105,0,17,0,0,1,20,33,21,32,17,16,33,32,17,16,33,53,32,55,52,33,32,1,18,1,36,254,30,2,38,2,4,254,62,1,2,2,254,186, +254,152,6,37,187,126,1,63,1,62,254,194,254,193,126,187,197,0,0,0,1,0,83,4,230,5,19,7,105,0,21,0,0,1,20,33,21,32,17,16,33,32,17,20,7,51,21,33,61,1,32,55,52,33,32,1,17,1,37,254,29,2,38,2,4,62,212,253,169,1,1,2,254,186,254,152,6,37,187,126,1,63,1,62,254, +194,119,74,132,6,126,187,197,0,0,0,2,0,83,4,236,4,126,7,105,0,17,0,21,0,0,1,20,33,21,32,17,16,33,32,17,16,33,53,32,55,52,33,32,5,21,35,53,1,18,1,36,254,30,2,38,2,4,254,62,1,2,2,254,186,254,152,1,222,238,6,37,187,126,1,63,1,62,254,194,254,193,126,187, +197,78,220,220,0,0,0,2,0,83,4,230,5,19,7,105,0,21,0,25,0,0,1,20,33,21,32,17,16,33,32,17,20,7,51,21,33,61,1,32,55,52,33,32,5,21,35,53,1,17,1,37,254,29,2,38,2,4,62,212,253,169,1,1,2,254,186,254,152,1,221,238,6,37,187,126,1,63,1,62,254,194,119,74,132,6, +126,187,197,84,220,220,0,0,0,2,1,207,253,51,3,135,255,178,0,4,0,21,0,0,4,34,20,51,54,3,54,53,52,39,6,35,34,53,52,51,50,23,22,21,20,7,2,191,130,65,65,92,144,5,40,68,179,170,101,78,91,204,188,129,1,254,207,111,91,17,16,36,158,186,78,91,139,117,214,0,0, +2,1,120,253,142,3,153,255,175,0,5,0,26,0,0,4,34,20,51,50,53,19,34,53,52,55,38,53,52,50,21,20,6,21,20,51,50,53,17,51,17,20,2,5,44,23,21,114,243,62,74,234,109,130,158,132,178,44,21,254,87,146,115,62,10,91,121,117,63,123,69,66,88,1,70,254,186,195,0,0,2, +0,69,5,28,4,140,7,11,0,20,0,27,0,0,1,22,7,39,54,53,54,37,34,7,22,7,6,7,6,39,38,55,54,33,32,0,52,7,34,23,20,51,4,140,1,168,138,86,1,254,165,65,33,46,10,21,217,229,1,1,123,120,1,26,2,57,252,225,60,63,1,56,6,10,95,143,138,70,46,85,1,4,68,87,176,1,1,217, +84,95,96,254,174,126,1,63,61,0,0,2,255,240,253,199,4,225,255,177,0,7,0,26,0,0,19,50,53,52,35,34,21,20,5,34,2,35,22,21,20,35,34,53,16,33,50,18,51,50,55,23,6,176,48,48,43,2,201,218,172,184,92,196,184,1,76,222,222,96,93,166,134,191,254,78,48,47,46,49,105, +1,51,32,114,191,167,1,67,254,208,198,114,240,0,1,2,14,4,241,2,195,6,86,0,3,0,0,1,51,17,35,2,14,180,180,6,86,254,155,0,0,0,2,0,86,4,224,4,123,7,32,0,7,0,27,0,0,19,22,39,54,7,34,23,6,37,20,2,41,1,53,54,53,6,55,52,23,22,29,1,20,7,32,54,53,241,42,1,1,42, +44,2,2,3,181,214,254,132,254,85,144,183,1,157,145,71,1,177,243,6,109,1,43,43,2,41,44,125,229,254,221,133,46,112,7,157,136,1,1,131,183,92,40,141,250,0,0,0,1,0,95,4,200,5,80,6,243,0,52,0,0,1,34,17,16,33,50,22,55,54,55,54,51,50,21,20,7,22,55,54,55,51,6, +7,6,33,35,53,54,53,52,35,34,7,6,39,38,39,38,35,34,21,20,59,1,38,53,52,51,22,7,6,7,6,1,80,240,1,36,50,126,42,38,74,72,72,220,158,132,66,80,4,154,2,104,40,254,226,196,208,76,24,66,68,92,106,36,62,24,146,102,62,46,96,104,2,2,62,52,4,200,1,20,1,23,130,1, +1,65,63,215,126,61,4,13,16,104,130,92,36,133,107,98,56,58,59,1,1,45,70,144,161,2,95,90,1,107,102,50,41,0,0,0,0,1,1,73,4,224,3,136,7,30,0,11,0,0,1,53,51,53,51,21,51,21,35,21,35,53,1,74,216,142,216,216,142,5,184,142,216,216,142,216,216,0,0,0,255,255,255, +240,5,23,4,225,7,1,16,7,4,218,0,0,7,80,0,0,0,2,1,150,4,246,3,59,6,114,0,7,0,12,0,0,1,52,51,50,21,20,35,34,18,20,51,50,52,1,150,212,208,212,208,132,76,84,5,190,180,180,200,1,16,144,144,0,0,1,0,160,0,0,4,51,4,122,0,21,0,0,1,2,33,32,17,52,55,51,6,21,16, +33,32,17,52,39,36,3,51,22,23,4,4,51,1,254,49,254,61,80,190,85,1,15,1,17,189,254,220,2,181,1,126,1,105,1,239,254,17,1,201,105,98,99,87,254,183,1,79,214,74,102,1,20,161,51,130,0,0,0,0,2,0,158,0,0,4,52,6,22,0,18,0,26,0,0,1,16,33,32,3,18,37,53,54,39,38,53, +51,20,23,22,29,1,4,3,18,33,4,17,16,33,32,4,52,254,60,254,49,3,3,1,131,1,163,141,181,126,161,1,107,188,1,254,239,254,241,1,22,1,9,2,32,253,224,2,33,1,171,84,138,120,28,27,189,89,27,57,185,144,118,254,119,1,115,3,254,149,254,107,0,2,0,110,254,87,4,97,4, +21,0,25,0,33,0,0,37,16,33,32,17,18,37,54,55,52,35,34,23,20,23,7,38,53,16,33,32,3,20,7,21,4,3,16,37,32,3,16,37,4,4,97,254,9,254,4,1,2,28,108,2,213,183,1,15,137,46,1,95,1,139,1,122,1,45,179,254,190,254,182,2,1,70,1,72,43,254,44,1,212,1,205,5,83,169,142, +139,46,43,82,76,111,1,9,254,219,164,84,20,110,254,181,1,66,1,254,189,254,192,1,1,0,0,0,0,2,0,55,254,87,4,154,4,11,0,33,0,44,0,0,23,54,55,53,0,17,16,5,50,23,51,54,51,32,17,21,16,33,32,17,53,52,43,1,34,17,21,16,0,23,7,38,36,7,1,53,52,43,1,34,29,1,16,51, +50,221,40,84,254,222,1,88,91,80,20,60,170,1,102,254,166,254,170,73,43,129,2,121,104,202,90,254,203,116,2,212,149,71,119,186,153,225,44,18,11,1,22,1,200,1,198,1,98,98,254,43,20,254,6,2,15,234,93,254,196,109,254,76,254,255,200,1,167,14,86,3,3,212,241,182, +247,254,232,0,0,1,0,160,254,87,4,51,4,21,0,26,0,0,5,2,33,32,17,52,55,51,6,21,16,33,32,53,17,16,32,21,20,23,7,38,53,16,5,32,19,4,51,1,254,73,254,37,141,188,144,1,36,1,6,254,38,62,176,56,1,150,1,157,1,32,254,119,1,146,143,106,115,133,254,251,241,2,164, +1,13,222,111,101,1,75,133,1,114,1,254,100,0,1,0,158,254,87,4,50,4,21,0,39,0,0,5,16,33,32,3,54,55,51,6,21,16,33,32,61,1,52,43,1,53,51,22,55,52,35,32,7,22,23,35,38,53,16,33,32,17,20,7,21,22,17,4,50,254,52,254,58,2,2,105,192,112,1,13,1,20,237,73,73,226, +1,225,254,252,1,1,45,161,60,1,177,1,158,229,237,45,254,132,1,152,93,109,120,82,254,246,223,98,243,140,1,240,243,202,88,120,82,126,1,88,254,123,209,92,20,43,254,254,0,0,0,0,3,0,158,0,0,4,50,6,20,0,17,0,24,0,32,0,0,1,2,33,32,17,16,55,53,38,55,2,33,32,17, +6,7,21,4,3,16,5,4,19,2,32,3,52,39,34,21,6,23,54,4,50,1,254,53,254,56,200,200,1,1,1,84,1,87,1,92,1,70,185,254,235,254,245,1,1,2,32,205,190,168,1,186,175,1,248,254,8,1,249,1,73,74,20,58,233,1,81,254,189,155,85,20,45,254,92,1,112,2,1,254,144,254,152,4,33, +212,2,214,218,1,1,0,0,2,0,55,0,0,4,154,4,11,0,26,0,37,0,0,1,21,16,7,35,54,17,53,16,43,1,34,29,1,16,33,32,17,53,16,33,50,23,51,54,51,32,1,17,54,35,7,38,17,21,16,51,50,4,154,239,162,212,132,33,83,254,203,254,135,1,125,146,71,14,74,116,1,65,253,170,2,70, +87,180,165,172,2,72,67,254,162,167,174,1,66,117,1,25,182,220,254,20,2,7,30,1,230,99,99,253,121,1,105,145,1,1,254,239,189,254,225,0,0,0,1,0,160,0,0,4,50,4,21,0,17,0,0,1,16,7,35,18,3,16,33,32,17,16,19,35,38,19,2,33,32,4,50,240,146,201,1,254,252,254,230, +198,148,238,2,2,1,210,1,195,2,35,254,165,200,1,4,1,31,1,99,254,160,254,230,254,244,207,1,90,1,236,0,0,0,0,1,0,158,254,89,4,52,4,2,0,31,0,0,5,2,33,32,17,52,55,51,6,21,16,33,32,61,1,16,43,1,53,51,50,53,52,33,53,32,17,22,5,21,4,19,4,52,1,254,67,254,40,112, +173,98,1,29,1,2,238,65,65,228,254,90,2,90,1,254,245,1,26,2,30,254,119,1,167,139,102,113,128,254,230,252,50,1,16,152,198,230,154,254,128,208,49,20,49,254,216,0,0,0,0,1,0,160,254,87,4,50,4,21,0,27,0,0,1,32,17,16,0,21,35,38,36,7,39,54,63,1,2,17,16,33,32, +17,20,6,23,7,38,54,53,16,2,108,254,237,2,95,190,36,254,179,94,77,62,112,13,249,1,204,1,198,118,20,159,20,92,3,136,254,189,254,89,254,49,120,176,79,104,95,91,13,14,1,5,1,130,1,203,254,41,101,181,156,1,157,168,117,1,71,0,2,0,158,0,0,4,52,6,21,0,21,0,28, +0,0,1,16,33,32,17,16,33,50,23,51,17,52,33,6,29,1,35,53,16,33,32,17,3,16,32,17,2,33,32,4,52,254,69,254,37,1,203,196,68,20,254,228,232,187,1,163,1,203,188,253,226,1,1,30,1,1,1,239,254,17,2,13,2,9,125,1,2,237,1,152,62,62,1,38,254,134,253,84,1,151,254,137, +254,130,0,2,0,159,0,0,4,50,5,251,0,17,0,25,0,0,1,18,33,32,25,1,2,41,1,21,33,34,21,17,51,54,51,4,3,16,33,32,17,16,37,4,4,50,1,254,50,254,58,1,1,77,1,206,254,30,141,35,64,184,1,205,185,254,234,254,239,1,17,1,22,2,36,253,220,1,234,2,182,1,91,143,176,254, +218,128,1,254,12,1,103,254,133,254,132,1,1,0,0,0,0,1,0,55,0,0,4,154,4,11,0,35,0,0,1,20,7,35,54,53,17,52,7,35,34,21,17,35,17,52,43,1,34,21,17,6,23,35,38,61,1,16,33,50,23,51,54,51,32,17,4,154,188,179,179,153,75,64,160,66,77,148,2,203,194,199,1,123,104, +73,17,70,96,1,128,1,198,236,218,192,207,1,25,215,1,207,254,235,1,21,207,228,254,252,214,192,225,236,102,1,216,104,104,254,38,0,0,0,0,1,0,160,0,0,4,52,6,15,0,33,0,0,1,16,33,32,19,52,55,51,6,21,16,33,32,17,16,33,35,53,51,50,55,52,37,36,53,51,20,23,4,17, +20,7,21,22,4,52,254,68,254,39,1,101,175,91,1,31,1,0,254,236,63,82,215,1,254,233,254,220,172,239,1,87,186,232,1,218,254,38,1,178,183,90,126,147,254,223,1,73,1,74,135,200,149,33,54,176,71,41,41,254,251,203,61,20,105,0,0,0,0,1,0,159,254,89,4,51,4,50,0,23, +0,0,5,2,33,32,3,51,6,33,32,25,1,5,21,22,21,16,5,53,32,39,18,37,53,37,4,51,1,254,48,254,62,1,187,1,1,4,1,39,254,77,221,253,241,1,104,1,1,254,152,3,148,18,254,107,1,111,227,1,11,3,168,52,60,89,238,254,206,1,167,140,1,3,75,130,129,0,0,0,0,1,0,55,0,0,4,154, +6,21,0,41,0,0,1,21,20,7,35,54,61,1,16,43,1,34,21,17,35,19,54,43,1,34,17,21,20,23,35,38,17,53,52,0,37,23,4,3,51,55,50,23,51,54,51,32,4,154,208,197,216,132,88,65,160,1,1,74,124,103,230,210,210,1,90,1,167,25,254,150,218,24,86,165,72,15,73,160,1,58,2,84, +142,244,210,184,219,193,1,42,167,254,195,1,61,167,254,219,165,252,184,210,1,24,103,251,2,78,123,148,82,254,159,61,98,98,0,0,0,1,0,159,0,0,4,51,5,241,0,21,0,0,1,16,33,32,25,1,51,17,16,33,32,17,52,36,53,52,55,23,6,21,20,4,4,51,254,61,254,47,182,1,27,1, +9,254,241,206,87,142,1,50,2,3,253,253,2,3,3,238,252,18,254,142,1,114,175,161,103,148,125,124,56,59,67,188,0,0,0,2,0,45,254,89,4,164,4,234,0,10,0,21,0,0,19,16,37,3,51,3,4,17,2,33,32,19,16,33,32,17,16,37,19,35,19,4,45,1,250,15,166,15,1,245,2,253,202,253, +193,188,1,127,1,134,254,193,15,165,14,254,194,1,34,2,117,82,1,1,254,251,78,253,133,253,61,2,201,253,195,2,61,1,231,111,253,229,2,26,110,0,0,1,0,55,254,89,4,74,4,12,0,41,0,0,5,2,33,32,17,52,55,51,6,21,16,33,32,53,17,52,35,6,17,7,35,39,16,39,14,1,35,34, +39,55,22,51,50,54,51,50,23,51,54,23,36,19,4,74,2,254,77,254,31,145,179,138,1,39,1,3,130,132,10,133,9,110,62,62,62,72,83,50,62,43,51,60,76,103,69,20,72,137,1,43,1,43,254,132,1,164,159,90,123,126,254,232,240,2,234,191,1,254,242,193,193,1,14,1,1,134,95, +181,98,99,184,184,1,1,254,179,0,0,0,2,0,55,254,87,4,157,4,11,0,45,0,56,0,0,5,16,33,35,32,17,51,20,59,1,32,61,1,52,39,35,53,51,54,61,1,52,43,1,34,29,1,16,33,4,17,53,16,33,50,23,51,54,51,32,17,20,7,21,22,21,1,52,43,1,34,17,21,16,51,50,17,4,157,254,52,56, +254,82,183,249,47,1,22,57,80,80,54,100,83,59,254,190,254,142,1,119,138,67,17,96,139,1,35,158,161,253,165,94,77,162,176,157,61,254,148,1,133,247,222,101,166,2,151,1,148,182,204,123,202,254,32,1,1,153,128,1,154,99,99,254,109,251,84,20,91,142,2,171,167, +254,250,120,254,215,1,5,0,0,0,1,0,160,254,87,4,49,5,241,0,30,0,0,37,16,33,32,17,52,55,23,6,21,16,33,32,3,19,16,5,38,21,20,23,35,38,53,16,33,22,23,51,19,51,4,49,254,84,254,27,134,176,125,1,41,1,1,1,2,254,223,197,82,179,70,1,113,142,124,17,1,173,67,254, +20,1,169,132,100,1,121,113,254,232,1,94,1,40,2,30,3,3,164,182,89,111,160,1,49,1,189,2,153,0,1,0,55,254,86,4,154,4,12,0,43,0,0,23,54,55,53,0,17,53,16,33,22,23,51,54,55,4,17,21,20,15,1,54,61,1,52,43,1,34,21,17,35,17,52,43,1,34,17,21,16,0,23,39,38,36,7, +237,57,65,254,208,1,95,131,74,16,70,149,1,76,169,140,120,134,100,58,160,65,76,151,2,150,69,203,25,254,196,130,201,83,2,22,1,5,1,39,80,1,238,1,103,103,1,1,254,63,70,244,177,1,167,174,219,240,175,254,203,1,53,175,254,250,138,254,141,254,179,216,1,142,112, +122,0,0,0,1,0,158,254,89,4,50,3,247,0,26,0,0,5,16,33,32,17,51,16,5,36,61,1,35,6,35,32,17,16,37,51,4,21,16,33,32,53,17,51,4,50,254,70,254,38,188,1,30,1,7,20,88,175,254,58,1,23,216,254,204,1,11,1,27,179,47,254,136,1,144,254,252,1,1,240,244,98,1,229,1,4, +167,206,221,254,175,235,2,9,0,0,2,0,55,0,0,4,52,6,20,0,31,0,39,0,0,1,16,33,32,3,16,37,22,23,51,17,52,35,34,29,1,35,53,52,35,34,21,35,16,51,50,23,51,54,51,32,11,1,2,33,32,19,2,33,50,4,52,254,89,254,18,1,1,198,193,70,20,142,141,157,160,85,155,220,186,63, +20,58,172,1,46,2,184,1,254,233,254,247,1,1,1,56,232,1,221,254,35,2,13,2,8,1,1,129,1,33,213,210,33,35,208,226,1,108,193,193,254,192,253,47,1,133,254,133,254,132,0,0,2,0,158,0,0,4,52,6,20,0,19,0,29,0,0,1,22,19,2,5,35,36,19,16,37,36,25,1,35,19,16,33,32, +19,22,39,38,35,34,21,17,51,54,5,54,3,77,230,1,1,254,233,178,1,14,1,254,250,254,221,178,2,1,112,1,127,30,1,164,30,217,195,30,63,1,37,56,3,218,104,254,146,254,184,188,199,1,65,1,106,1,19,254,197,253,181,4,190,1,86,254,199,96,77,191,214,254,228,128,30,134, +0,1,0,86,254,89,4,122,4,37,0,35,0,0,1,20,7,21,22,21,2,33,32,17,53,16,19,23,6,3,21,18,33,32,3,54,43,1,53,51,50,39,54,39,38,39,51,20,23,22,4,92,171,201,2,253,247,253,231,209,145,164,1,1,1,92,1,88,1,1,183,184,176,164,1,1,161,143,1,183,130,167,2,133,153, +88,20,123,191,254,19,2,195,97,1,68,1,100,76,250,254,219,158,253,201,1,130,218,136,184,119,47,46,173,125,46,56,0,0,0,0,2,0,158,0,0,4,51,5,241,0,11,0,19,0,0,1,18,33,32,17,16,33,50,23,51,17,51,3,16,33,32,17,16,33,32,4,51,2,254,47,254,58,1,198,215,50,20, +178,186,254,234,254,246,1,9,1,23,2,5,253,251,1,253,2,25,115,2,78,252,22,1,128,254,118,254,148,0,0,0,0,2,0,161,0,0,4,156,6,20,0,31,0,39,0,0,19,2,33,50,23,51,54,51,50,17,35,52,35,34,29,1,35,53,52,35,34,21,17,51,54,55,32,17,2,5,32,17,55,18,51,36,3,18,5, +32,161,2,1,48,172,58,20,63,186,218,153,85,160,157,141,142,20,70,193,1,193,1,254,43,254,69,186,1,252,1,34,1,1,254,249,254,233,4,212,1,64,193,193,254,148,226,208,35,33,210,213,254,223,129,1,253,238,253,253,1,2,15,38,254,92,1,1,114,1,133,1,0,0,2,0,160,254, +89,4,52,5,241,0,37,0,45,0,0,5,16,33,32,19,52,55,23,6,21,20,5,32,3,52,39,38,39,7,32,17,16,33,23,17,51,17,22,23,51,21,35,20,15,1,22,23,22,1,20,51,22,39,54,35,38,4,52,254,52,254,54,2,81,143,38,1,14,1,17,1,176,113,3,89,254,203,1,65,77,157,94,1,184,189,82, +1,1,172,141,253,66,163,171,1,1,162,172,20,254,109,1,149,105,94,105,36,73,250,1,1,8,160,99,111,102,19,1,72,1,77,9,1,180,254,1,59,105,162,105,55,72,65,105,97,2,66,201,3,204,193,1,0,2,0,159,0,0,4,52,5,241,0,11,0,19,0,0,1,2,33,32,25,1,51,17,51,54,51,4,3, +16,33,32,17,16,33,32,4,52,1,254,57,254,51,171,41,74,175,1,200,187,254,242,254,238,1,20,1,12,2,13,253,243,2,13,3,228,253,161,132,1,253,248,1,123,254,131,254,134,0,0,0,1,0,159,254,89,4,52,4,215,0,31,0,0,37,16,33,32,17,52,55,23,6,21,16,5,32,17,54,39,38, +39,53,37,53,5,53,51,17,5,21,37,21,20,23,22,4,52,254,46,254,61,107,144,64,1,8,1,22,1,194,170,1,254,185,1,71,146,1,80,254,176,215,190,41,254,48,1,207,125,140,89,105,71,254,190,1,1,66,173,157,171,135,160,120,180,128,232,254,243,127,177,134,125,72,186,183, +0,0,1,0,158,0,0,4,52,6,20,0,43,0,0,1,16,33,32,17,53,51,21,2,33,32,39,52,39,35,53,51,50,53,54,43,1,53,51,50,55,52,37,38,53,51,20,5,22,21,20,7,21,22,21,20,7,21,22,4,52,254,55,254,51,188,1,1,12,1,21,2,108,251,251,100,1,101,251,249,91,1,255,0,233,166,1,20, +233,144,154,148,158,1,104,254,152,1,160,101,101,254,236,212,174,1,150,122,115,152,132,85,32,33,208,120,26,26,190,140,47,20,54,137,126,58,20,95,0,0,1,0,118,254,89,4,51,6,20,0,61,0,0,5,2,33,32,17,16,19,54,3,51,18,3,6,3,18,33,50,39,52,39,35,53,51,54,53, +52,43,1,53,51,50,53,52,7,35,53,51,50,53,38,39,38,39,51,20,23,22,23,6,7,21,22,23,6,7,21,22,23,6,7,21,22,4,51,1,254,84,253,240,55,54,104,185,84,37,49,1,1,1,84,251,2,134,136,136,134,132,138,138,132,134,136,136,134,1,185,145,1,166,189,156,1,1,178,178,1,1, +178,178,1,2,177,178,124,254,213,1,216,1,43,1,13,227,1,63,254,249,254,229,225,254,169,254,179,160,198,2,142,1,134,164,138,156,132,1,145,142,82,33,34,178,72,54,49,152,165,34,20,40,159,187,30,20,38,183,146,48,20,58,0,0,2,0,160,254,243,4,52,4,22,0,17,0,25, +0,0,23,50,55,36,17,18,37,32,17,16,5,22,55,21,36,39,6,7,19,16,5,36,3,18,33,32,201,149,80,254,242,3,1,197,1,204,254,231,92,143,254,248,150,193,222,144,1,15,1,18,1,1,254,233,254,246,60,89,170,1,64,2,14,1,253,241,254,192,170,94,5,209,69,194,193,70,3,20,254, +196,85,85,1,60,1,127,0,0,0,1,0,159,254,87,4,52,4,21,0,29,0,0,5,2,5,32,17,55,23,7,18,33,32,17,53,16,5,35,53,51,32,19,39,5,21,35,17,37,16,5,4,17,4,52,1,254,48,254,60,31,180,21,1,1,10,1,14,254,194,114,114,1,30,1,2,254,32,173,3,108,254,236,1,20,20,254,109, +2,1,149,111,20,91,254,249,1,7,32,1,43,1,160,1,101,74,30,204,1,93,29,254,48,185,113,254,241,0,1,0,159,254,87,4,52,6,21,0,36,0,0,5,16,33,32,17,51,16,33,32,17,53,52,33,35,53,51,36,17,6,35,4,17,16,5,21,32,21,20,33,50,55,17,18,5,21,4,21,4,52,254,52,254,55, +190,1,11,1,13,254,237,156,156,1,20,125,143,254,53,1,203,254,200,1,54,238,221,1,254,203,1,53,20,254,107,1,149,254,248,1,8,55,236,157,11,1,158,37,3,1,100,1,133,1,142,246,210,168,254,248,254,117,105,20,62,246,0,0,3,0,139,0,0,4,124,6,21,0,23,0,31,0,39,0, +0,1,21,16,33,32,17,16,37,33,53,33,36,17,16,33,32,17,21,51,21,35,21,51,21,37,33,32,21,20,33,32,53,1,20,41,1,53,52,33,32,4,10,254,73,254,56,1,196,1,17,254,239,254,60,1,204,1,179,114,114,114,254,228,254,239,254,250,1,14,1,9,253,233,1,6,1,17,254,247,254, +242,2,5,182,254,177,1,79,1,102,2,161,1,1,107,1,81,254,175,216,148,161,178,30,206,201,211,3,99,214,216,195,0,0,0,2,0,55,254,88,4,154,4,22,0,33,0,44,0,0,1,16,33,34,39,35,21,2,33,53,50,39,17,52,35,7,38,21,17,20,51,21,36,17,53,16,33,50,23,51,54,51,4,17,3, +17,52,43,1,34,21,17,20,51,50,4,154,254,205,126,26,15,11,254,179,183,9,77,97,115,128,254,194,1,49,183,68,16,62,182,1,51,189,136,76,73,167,118,1,150,254,106,116,152,254,124,142,231,3,9,178,1,1,189,254,193,217,148,3,1,120,240,1,140,145,145,1,254,117,254, +174,1,161,175,167,254,131,211,0,0,0,1,0,107,254,89,4,102,4,22,0,31,0,0,33,2,33,32,3,16,37,36,53,52,35,34,7,23,7,39,16,33,32,17,6,5,4,17,2,33,32,19,52,39,55,22,4,102,1,253,245,254,18,1,1,71,1,68,152,181,1,5,165,10,1,96,1,85,1,254,175,254,200,1,1,54,1, +73,1,64,154,98,254,89,1,167,1,115,114,103,127,188,159,56,21,65,1,58,254,168,212,131,77,254,238,254,220,1,41,123,54,92,108,0,0,0,0,1,0,161,254,89,4,52,4,40,0,27,0,0,19,51,17,22,33,32,17,52,37,55,4,19,16,37,35,34,39,35,21,2,37,32,17,51,2,33,32,17,161,173, +1,1,35,1,7,254,249,171,1,22,1,254,62,2,185,85,20,2,1,38,1,7,187,1,254,59,254,51,3,254,253,204,191,1,48,253,177,63,226,254,245,254,55,1,89,227,254,251,1,1,4,254,112,1,140,0,0,2,0,110,254,87,4,99,4,36,0,22,0,30,0,0,19,2,33,4,17,16,5,4,21,20,23,54,61,1, +51,21,2,33,32,17,52,55,36,19,22,5,36,53,16,33,32,110,1,2,0,1,246,254,150,254,218,158,195,178,1,254,140,254,170,239,254,100,191,1,1,63,1,59,254,197,254,192,2,107,1,185,1,254,72,254,235,169,117,158,181,1,1,140,76,76,254,230,1,56,231,84,87,1,74,255,38,41, +252,1,42,0,0,1,0,160,255,121,3,164,4,22,0,26,0,0,5,53,52,38,35,34,7,39,54,55,53,38,17,16,37,4,1,39,0,37,32,3,30,1,23,22,23,2,239,116,95,130,67,130,67,116,236,1,228,2,167,254,121,145,1,17,254,96,254,220,1,3,94,113,178,124,135,1,5,121,116,74,102,24,30, +173,1,73,1,181,1,56,253,5,61,2,92,11,254,219,163,202,98,42,147,0,0,3,1,35,0,50,3,174,3,227,0,3,0,7,0,11,0,0,1,51,21,35,5,51,21,35,5,51,21,35,1,35,192,192,1,209,186,186,254,47,189,189,3,227,176,189,174,232,174,0,0,0,0,2,1,149,2,245,3,59,6,20,0,15,0,23, +0,0,1,50,3,16,7,34,25,1,52,59,1,21,37,34,29,1,23,52,35,34,7,20,51,50,2,108,208,1,213,209,185,235,254,254,70,237,124,112,1,117,120,5,36,254,239,254,227,1,1,30,1,76,181,82,2,81,158,194,180,186,201,0,0,0,0,3,0,41,255,227,4,176,4,123,0,10,0,18,0,66,0,0,1, +21,51,50,54,53,52,38,35,34,6,1,21,20,22,50,54,61,1,37,33,62,1,53,52,38,35,34,6,7,53,62,1,51,50,22,23,62,1,51,50,22,21,20,6,43,1,21,20,22,51,50,54,55,21,14,1,35,34,38,39,14,1,35,34,38,17,2,186,49,169,120,89,83,92,74,254,19,77,174,76,254,21,1,235,1,1,101, +112,79,129,50,55,132,71,110,149,32,39,133,97,156,163,200,191,117,99,94,56,132,62,77,132,60,91,124,37,33,132,89,174,145,2,164,72,90,113,89,97,133,254,113,52,151,133,136,157,43,143,15,35,34,161,144,51,51,172,41,43,82,78,80,80,172,164,171,179,88,120,128, +43,39,168,35,33,63,64,61,66,237,1,50,0,0,0,1,0,169,255,234,4,40,4,123,0,48,0,0,1,22,23,22,21,20,6,35,34,39,38,39,53,22,23,22,51,50,54,53,52,39,38,43,1,53,51,50,54,53,52,39,38,35,34,7,6,7,53,54,55,54,51,50,23,22,21,20,6,3,16,119,65,64,244,209,81,91,92, +105,104,87,86,76,138,148,72,72,135,166,159,150,168,90,91,173,99,91,91,77,97,90,91,86,254,139,138,148,2,6,25,65,64,94,134,158,12,12,24,167,27,13,12,86,74,61,43,44,144,110,81,98,53,52,18,17,34,173,28,14,14,91,92,166,109,148,0,2,0,178,254,80,4,68,4,100, +0,9,0,13,0,0,37,33,17,33,53,33,21,33,17,33,1,35,53,51,3,246,254,41,254,147,3,146,254,147,1,31,254,225,184,184,4,3,209,143,143,252,190,253,189,233,0,3,0,14,255,227,4,186,4,123,0,10,0,21,0,54,0,0,19,20,6,21,20,22,51,50,54,61,1,1,34,6,21,16,22,51,50,54, +16,38,1,33,53,52,38,35,34,6,7,53,62,1,51,50,22,23,62,1,51,50,18,16,2,35,34,38,39,14,1,35,34,38,17,177,2,80,86,87,77,1,90,102,82,80,104,103,80,80,252,84,1,235,99,112,80,131,47,59,125,74,98,147,48,52,128,84,189,170,170,189,89,128,47,37,130,87,175,144,1, +205,11,38,9,145,135,137,158,43,2,22,168,239,254,221,174,167,2,26,167,254,121,84,163,144,53,51,172,43,41,67,66,68,65,254,236,253,144,254,236,62,65,62,65,237,1,50,0,0,0,1,0,137,2,47,4,72,4,123,0,12,0,0,19,16,18,32,18,17,35,52,38,35,34,6,21,137,246,1,210, +247,195,144,141,140,144,2,47,1,30,1,46,254,210,254,226,214,218,218,214,0,0,1,0,136,255,227,4,71,2,47,0,12,0,0,1,16,2,32,2,17,51,20,22,51,50,54,53,4,71,246,254,46,247,195,144,141,140,144,2,47,254,226,254,210,1,46,1,30,214,218,218,214,0,1,0,43,0,2,4,166, +3,91,0,19,0,0,37,33,53,33,50,54,53,52,38,35,33,53,33,21,35,30,1,21,20,6,2,225,253,74,2,182,151,142,183,171,253,135,4,94,168,97,100,225,2,184,108,112,130,138,184,184,50,168,114,172,168,0,0,0,0,3,0,63,255,254,4,146,3,87,0,3,0,7,0,27,0,0,55,53,51,21,3,53, +51,21,1,33,53,33,50,54,53,52,38,35,33,53,33,21,35,30,1,21,20,6,63,142,142,142,2,136,254,26,1,230,105,100,128,120,254,69,3,15,118,68,70,158,122,204,204,1,136,202,202,253,252,184,108,112,130,138,184,184,50,168,114,172,168,0,0,0,0,1,0,43,0,1,4,166,4,3,0, +34,0,0,1,30,1,21,20,6,41,1,53,33,50,54,53,52,38,35,33,53,33,50,54,53,52,38,35,33,53,33,21,35,30,1,21,20,6,4,25,72,69,209,254,223,253,119,2,129,237,115,123,229,253,127,2,129,240,112,123,229,253,127,4,96,96,60,63,70,1,204,34,105,74,135,111,168,53,70,80, +59,168,57,74,73,57,167,167,33,99,63,76,101,0,2,0,252,2,156,3,214,5,224,0,2,0,10,0,0,1,3,33,3,51,1,35,39,33,7,35,2,104,134,1,12,210,154,1,32,132,68,254,182,68,132,5,124,254,85,2,15,252,188,218,218,0,2,0,245,2,156,3,220,5,224,0,15,0,19,0,0,1,21,35,21,51, +21,35,17,51,21,33,53,35,7,35,1,23,3,51,17,3,208,213,194,194,225,254,170,221,64,116,1,2,76,127,194,5,224,95,248,95,254,209,95,214,214,3,68,95,254,80,1,176,0,0,0,0,3,1,55,2,156,3,154,5,224,0,8,0,17,0,32,0,0,1,17,51,50,54,53,52,38,35,3,21,51,50,54,53,52, +38,35,37,33,50,22,21,20,6,7,30,1,21,20,6,35,33,1,182,151,111,94,99,106,151,149,91,83,81,93,254,236,1,22,144,157,83,83,93,105,167,166,254,234,4,43,254,206,69,79,82,76,1,88,252,63,70,63,56,93,111,101,77,88,12,12,116,89,114,116,0,2,1,55,2,156,3,154,5,224, +0,8,0,17,0,0,1,50,54,53,52,38,43,1,17,19,50,22,21,20,6,43,1,17,1,244,160,128,127,161,61,63,216,204,204,216,191,2,249,141,183,186,140,253,118,2,231,204,215,214,203,3,68,0,0,1,1,76,2,156,3,134,5,224,0,11,0,0,1,33,21,33,21,33,21,33,17,33,21,33,1,76,2,46, +254,80,1,156,254,100,1,188,253,198,5,224,95,248,95,254,209,95,0,1,1,76,2,156,3,134,5,224,0,11,0,0,1,17,33,53,33,17,33,53,33,53,33,53,3,134,253,198,1,186,254,100,1,156,254,82,5,224,252,188,95,1,47,95,248,95,0,1,1,44,2,140,3,164,5,239,0,28,0,0,1,14,1,35, +34,38,16,54,51,50,22,23,21,46,1,35,34,6,21,20,22,51,50,54,55,53,35,53,33,3,164,52,126,76,178,200,202,180,60,108,50,52,106,60,124,124,120,124,42,64,26,136,1,2,2,225,42,43,228,1,154,229,29,31,116,43,41,170,172,174,167,17,18,225,93,0,0,0,0,1,1,58,2,156, +3,150,5,224,0,11,0,0,1,51,17,33,17,51,17,35,17,33,17,35,1,58,128,1,94,126,126,254,162,128,5,224,254,169,1,87,252,188,1,142,254,114,0,1,1,100,2,156,3,110,5,224,0,11,0,0,1,33,21,35,17,51,21,33,53,51,17,35,1,100,2,10,198,198,253,246,196,196,5,224,95,253, +122,95,95,2,134,0,0,0,0,1,1,94,2,140,3,115,5,224,0,17,0,0,1,53,30,1,51,50,54,53,17,35,53,33,17,20,6,35,34,38,1,94,57,122,66,90,71,240,1,111,133,155,61,119,2,190,132,45,45,83,114,1,212,95,253,205,158,131,24,0,0,0,0,1,1,18,2,156,3,192,5,224,0,11,0,0,1, +51,17,1,51,9,1,35,1,7,17,35,1,18,128,1,142,148,254,146,1,122,154,254,204,96,128,5,224,254,140,1,116,254,170,254,18,1,163,92,254,185,0,1,1,69,2,156,3,140,5,224,0,5,0,0,1,51,17,33,21,33,1,69,128,1,199,253,185,5,224,253,27,95,0,1,1,27,2,156,3,182,5,224, +0,12,0,0,1,51,27,1,51,17,35,17,3,35,3,17,35,1,27,170,163,164,170,117,168,96,169,117,5,224,254,86,1,170,252,188,2,227,254,71,1,185,253,29,0,0,0,1,1,60,2,156,3,149,5,224,0,9,0,0,1,51,1,17,51,17,35,1,17,35,1,60,161,1,61,123,161,254,194,122,5,224,253,80, +2,176,252,188,2,176,253,80,0,0,0,1,1,60,2,156,3,149,5,224,0,9,0,0,1,17,35,17,1,35,17,51,17,1,3,149,123,254,195,161,122,1,62,5,224,252,188,2,176,253,80,3,68,253,80,2,176,0,0,2,1,46,2,140,3,163,5,239,0,10,0,19,0,0,0,16,38,35,34,6,21,20,22,51,50,19,20,6, +32,38,16,54,32,22,3,30,85,97,96,85,85,96,97,218,156,254,194,155,155,1,62,156,3,133,1,112,158,158,184,183,158,1,85,218,215,214,1,182,215,215,0,2,1,63,2,156,3,146,5,224,0,8,0,18,0,0,1,17,51,50,54,53,52,38,35,37,33,50,22,20,6,43,1,17,35,1,190,148,88,99, +98,89,254,237,1,19,157,163,162,158,148,127,5,131,254,198,83,74,75,82,93,127,246,127,254,176,0,0,0,2,1,17,2,156,3,192,5,224,0,19,0,28,0,0,1,30,1,31,1,35,39,46,1,43,1,17,35,17,33,50,22,21,20,6,1,17,51,50,54,53,52,38,35,2,150,49,69,52,128,137,112,49,77, +62,122,128,1,6,155,165,101,254,159,139,92,89,95,91,4,39,11,63,93,228,211,90,52,254,159,3,68,124,118,83,104,1,80,254,215,73,75,72,77,0,0,1,1,2,2,156,3,207,5,224,0,7,0,0,1,33,21,33,17,35,17,33,1,2,2,205,254,218,128,254,217,5,224,95,253,27,2,229,0,0,0,1, +1,65,2,140,3,144,5,224,0,29,0,0,1,17,51,17,20,22,23,30,1,51,50,54,55,62,1,53,17,51,17,20,6,7,14,1,35,34,38,39,46,1,1,65,127,8,10,20,76,54,55,75,21,10,7,128,36,44,42,107,67,66,107,42,44,36,3,221,2,3,253,201,61,52,14,33,33,33,33,14,52,60,2,56,253,253,128, +108,36,33,32,32,33,35,110,0,0,0,0,1,0,228,2,156,3,237,5,224,0,12,0,0,19,51,27,1,51,27,1,51,3,35,11,1,35,228,124,90,107,133,109,90,124,141,120,128,127,121,5,224,253,89,1,193,254,62,2,168,252,188,1,241,254,15,0,2,1,69,2,140,3,140,5,30,0,11,0,41,0,0,1,35, +34,6,21,20,22,51,50,54,55,53,55,17,35,53,14,1,35,34,38,53,52,54,59,1,53,46,1,35,34,6,7,53,62,1,51,50,22,23,30,1,2,171,38,102,102,77,68,95,110,1,116,116,38,112,81,108,128,158,153,156,1,84,93,59,121,58,65,118,55,88,124,38,24,20,3,215,63,63,56,63,118,104, +23,43,254,154,93,56,53,108,91,104,109,16,75,68,30,29,103,21,22,46,46,28,82,0,0,2,1,69,2,140,3,140,5,30,0,11,0,41,0,0,1,51,50,54,53,52,38,35,34,6,7,21,7,17,51,21,62,1,51,50,22,21,20,6,43,1,21,30,1,51,50,54,55,21,14,1,35,34,38,39,46,1,2,38,38,102,102,77, +68,95,110,1,116,116,38,112,81,108,128,158,153,156,1,84,93,59,121,58,65,118,55,88,124,38,24,20,3,211,63,63,56,63,118,104,23,43,1,102,93,56,53,108,90,105,109,16,75,68,30,29,103,21,22,46,46,28,82,0,0,2,1,71,2,140,3,138,5,30,0,16,0,26,0,0,1,53,51,17,35,53, +14,1,35,34,38,53,52,54,51,50,22,4,20,22,51,50,54,52,38,35,34,3,22,116,116,29,96,63,128,147,147,128,63,97,254,199,86,84,83,88,88,83,84,4,191,78,253,143,79,47,48,176,155,153,174,48,161,240,122,123,238,123,0,3,0,251,2,140,3,214,5,30,0,10,0,18,0,66,0,0,1, +21,51,50,54,53,52,38,35,34,6,5,21,20,22,50,54,61,1,37,33,52,54,53,52,38,35,34,6,7,53,62,1,51,50,22,23,62,1,51,50,22,21,20,6,43,1,21,20,22,51,50,54,55,21,14,1,35,34,38,39,14,1,35,34,38,53,2,153,31,107,75,56,52,58,47,254,202,48,110,48,254,202,1,54,1,64, +70,50,81,32,35,83,45,69,94,20,25,84,61,98,103,126,121,73,62,59,35,84,39,49,83,38,57,78,24,20,84,56,109,92,4,23,41,51,63,50,54,74,224,29,85,74,76,88,24,80,9,19,19,90,81,28,29,96,23,24,46,43,45,44,96,92,96,100,49,67,72,24,22,94,20,18,35,36,34,37,132,172, +0,0,2,1,71,2,140,3,138,6,3,0,7,0,24,0,0,0,52,38,34,6,20,22,50,3,62,1,51,50,22,21,20,6,35,34,38,39,21,35,17,51,3,16,86,168,87,87,168,255,28,97,65,127,146,147,128,63,96,29,116,116,3,93,240,122,123,238,123,1,220,46,49,174,153,155,176,48,47,79,3,103,0,0, +0,0,2,1,71,2,140,3,138,6,3,0,16,0,26,0,0,1,17,51,17,35,53,14,1,35,34,38,53,52,54,51,50,22,4,20,22,51,50,54,52,38,35,34,3,22,116,116,29,96,63,128,147,147,128,63,97,254,199,86,84,83,88,88,83,84,4,191,1,68,252,153,79,47,48,176,155,153,174,48,161,240,122, +123,238,123,0,0,0,0,2,1,49,2,140,3,160,5,30,0,21,0,28,0,0,1,21,33,21,20,22,51,50,54,55,21,14,1,35,34,38,53,52,54,51,50,22,7,46,1,35,34,6,7,3,160,254,10,120,110,55,121,69,66,123,57,165,185,181,152,134,156,116,2,92,85,84,109,10,3,239,50,3,103,112,31,32, +102,24,24,175,154,150,179,162,110,90,95,98,87,0,0,2,1,49,2,140,3,160,5,30,0,21,0,28,0,0,1,53,33,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,35,34,38,55,30,1,51,50,54,55,1,49,1,246,120,110,55,121,69,66,123,57,165,185,181,152,134,156,116,2,92,85,84,109, +10,3,187,50,3,103,112,31,32,102,24,24,175,154,150,179,162,110,90,95,98,87,0,0,1,1,79,2,144,3,130,5,30,0,40,0,0,1,46,1,53,52,54,51,50,22,23,21,46,1,35,34,6,21,20,22,59,1,21,35,34,6,21,20,22,51,50,54,55,21,14,1,35,34,38,53,52,54,1,255,75,81,153,132,51, +115,67,66,109,48,87,93,91,85,104,100,94,106,114,109,62,115,48,61,114,54,160,174,93,3,240,14,72,53,75,88,13,14,93,15,14,48,42,34,48,81,62,45,55,59,20,19,97,16,15,102,93,61,83,0,1,1,79,2,144,3,130,5,30,0,40,0,0,1,30,1,21,20,6,35,34,38,39,53,30,1,51,50, +54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,2,210,75,81,153,132,51,115,67,66,109,48,87,93,91,85,104,100,94,106,114,109,62,115,48,61,114,54,160,174,93,3,190,14,72,53,75,88,13,14,93,15,14,48,42,34,48,81,62,45,55,59,20,19,97, +16,15,102,93,61,83,0,2,1,71,1,166,3,138,5,30,0,9,0,39,0,0,0,52,38,35,34,6,20,22,51,50,23,20,6,35,34,38,39,53,30,1,51,50,54,61,2,14,1,35,34,38,53,52,54,51,50,22,23,53,51,3,22,85,81,85,90,90,86,80,201,150,145,48,105,52,62,100,43,93,86,28,95,69,124,147, +147,124,68,94,30,116,3,103,232,120,120,232,122,41,141,145,15,15,102,25,25,91,98,5,70,53,51,175,148,147,176,48,50,81,0,0,0,2,1,73,1,170,3,136,5,17,0,9,0,13,0,0,1,33,17,35,53,33,21,35,17,51,3,35,53,51,3,87,254,216,230,2,63,230,181,181,115,115,2,158,2,35, +80,80,254,45,254,188,131,0,0,0,0,1,1,56,2,156,3,153,6,3,0,11,0,0,1,51,17,1,51,5,1,35,1,7,21,35,1,56,120,1,48,141,254,234,1,66,142,254,251,86,120,6,3,254,8,1,4,236,254,121,1,68,73,251,0,0,0,1,1,37,2,156,3,172,5,30,0,34,0,0,1,62,1,51,50,22,21,17,35,17, +52,38,35,34,6,21,17,35,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,22,2,139,21,66,47,85,70,106,34,44,50,37,106,36,47,46,35,106,106,20,63,39,48,64,4,207,41,38,117,162,254,149,1,103,133,64,69,128,254,153,1,103,134,63,69,128,254,153,2,115,54,34,35,39, +0,0,1,1,91,1,173,3,118,5,30,0,31,0,0,1,17,20,7,6,43,1,53,51,50,55,54,53,17,52,38,35,34,7,6,21,17,35,17,51,21,54,55,54,51,50,22,3,118,56,57,104,129,117,57,28,28,67,71,82,44,43,116,116,31,53,52,73,108,106,4,33,254,112,109,59,60,88,35,34,71,1,144,84,80, +51,52,96,254,158,2,115,94,54,28,27,126,0,2,1,58,2,140,3,151,5,30,0,11,0,22,0,0,1,34,6,21,20,22,51,50,54,53,52,46,1,32,22,21,20,6,35,34,38,53,52,2,104,88,91,91,88,89,91,91,236,1,38,156,155,148,147,155,4,199,122,120,119,123,123,119,120,122,87,169,160,161, +168,168,161,160,0,0,0,1,1,88,2,140,3,121,5,30,0,23,0,0,1,62,1,51,50,22,16,6,35,34,38,39,53,30,1,51,50,54,52,38,35,34,6,7,1,88,46,99,52,164,184,184,164,51,97,49,46,92,59,109,117,118,108,61,95,41,4,238,24,24,174,254,202,174,23,25,108,36,33,126,232,126, +33,35,0,0,0,1,1,58,3,213,3,151,5,30,0,12,0,0,1,52,54,32,22,21,35,52,38,35,34,6,21,1,58,155,1,38,156,123,91,89,88,91,3,213,160,169,169,160,120,122,122,120,0,1,1,58,2,140,3,151,3,213,0,12,0,0,1,20,6,32,38,53,51,20,22,51,50,54,53,3,151,155,254,218,156,123, +91,89,88,91,3,213,160,169,169,160,120,122,122,120,0,2,1,71,1,173,3,138,5,30,0,16,0,24,0,0,1,17,35,17,51,21,62,1,51,50,22,21,20,6,35,34,38,36,52,38,34,6,20,22,50,1,188,117,117,29,96,63,128,146,146,128,64,96,1,56,85,168,87,87,168,2,235,254,194,3,98,80, +47,48,176,155,153,174,48,161,240,122,123,238,123,0,0,0,0,1,1,77,2,156,3,132,5,193,0,19,0,0,1,21,33,21,33,17,20,22,59,1,21,35,34,38,53,17,35,53,51,53,2,125,1,7,254,249,59,74,130,141,131,107,188,188,5,193,178,80,254,172,70,55,82,93,114,1,84,80,178,0,0, +1,1,91,2,140,3,118,5,14,0,19,0,0,1,17,51,17,20,22,51,50,54,53,17,51,17,35,53,14,1,35,34,38,1,91,116,67,71,82,87,116,116,31,107,71,108,106,3,137,1,133,254,123,84,80,103,96,1,98,253,142,94,54,56,126,0,0,0,1,0,255,2,157,3,210,4,125,0,19,0,0,1,33,53,33,50, +54,53,52,38,35,33,53,33,21,35,30,1,21,20,6,2,180,254,75,1,181,96,89,115,108,254,113,2,193,106,61,63,142,2,157,103,60,63,73,77,104,104,27,95,63,97,94,0,0,0,1,1,37,2,156,3,172,5,30,0,34,0,0,1,14,1,35,34,38,53,17,51,17,20,22,51,50,54,53,17,51,17,20,22,51, +50,54,53,17,51,17,35,53,14,1,35,34,38,2,70,21,66,47,85,70,106,34,44,50,37,106,36,47,46,35,106,106,20,63,39,48,64,2,235,40,39,117,162,1,107,254,153,132,65,69,128,1,103,254,153,134,63,69,128,1,103,253,141,54,34,35,39,0,0,1,1,35,2,156,3,174,5,15,0,6,0,0, +1,51,27,1,51,3,35,1,35,120,205,206,120,251,149,5,15,253,242,2,14,253,141,0,0,0,255,255,1,72,0,0,3,136,3,103,18,7,7,71,0,0,253,100,0,0,255,255,1,153,0,0,3,56,2,131,18,7,2,89,0,0,253,100,0,0,255,255,1,91,255,240,3,118,2,114,18,7,5,65,0,0,253,100,0,0,255, +255,1,35,0,0,3,174,2,115,18,7,5,68,0,0,253,100,0,0,0,2,0,123,254,72,4,18,4,123,0,10,0,40,0,0,37,20,22,51,50,54,16,38,35,34,6,3,52,18,51,50,22,23,21,46,1,35,34,6,29,2,62,1,51,50,18,17,16,2,35,34,38,39,21,35,1,51,135,129,135,142,143,136,127,135,184,238, +231,76,166,83,98,160,67,149,136,44,152,109,196,234,234,196,108,150,47,184,138,207,215,215,1,158,217,218,1,35,252,1,4,28,27,182,46,44,162,176,8,125,94,92,254,198,254,249,254,248,254,198,86,90,145,0,255,255,1,58,2,156,3,150,5,224,16,6,5,30,0,0,0,1,0,156, +0,0,4,53,4,96,0,19,0,0,1,21,33,17,33,21,33,53,33,17,33,53,33,17,33,53,33,21,33,17,4,53,254,143,1,110,252,110,1,108,254,144,1,112,254,148,3,146,254,146,2,104,164,254,203,143,143,1,53,164,1,105,143,143,254,151,0,0,0,1,0,160,254,86,4,10,6,31,0,27,0,0,1, +20,22,59,1,29,2,20,7,6,43,1,53,51,50,55,54,61,1,35,34,38,53,17,33,53,33,2,127,91,89,215,89,90,165,205,185,90,45,44,48,165,181,254,217,1,223,1,150,124,126,28,128,20,195,105,106,156,62,62,126,20,212,194,3,249,144,0,0,0,0,2,1,71,2,140,3,138,5,30,0,16,0, +26,0,0,1,21,35,17,51,21,62,1,51,50,22,21,20,6,35,34,38,36,52,38,35,34,6,20,22,51,50,1,187,116,116,29,96,63,128,147,147,128,63,97,1,57,86,84,83,88,88,83,84,2,235,78,2,113,79,47,48,176,155,153,174,48,161,240,122,123,238,123,0,1,1,88,2,140,3,121,5,30,0, +24,0,0,1,14,1,35,34,38,16,54,51,50,22,23,21,46,1,35,34,6,21,20,22,51,50,54,55,3,121,46,99,52,164,184,184,164,51,97,49,46,92,59,109,117,118,108,61,95,41,2,188,24,24,174,1,54,174,23,25,108,36,33,125,117,116,126,33,35,0,2,1,81,2,73,3,128,5,28,0,7,0,43,0, +0,1,22,51,50,53,38,35,34,7,6,21,7,52,55,38,39,38,53,52,55,54,51,50,23,22,23,21,46,1,35,34,7,6,20,23,22,23,54,51,50,23,20,35,34,2,100,38,47,92,1,82,64,53,3,97,8,36,30,94,96,94,165,54,51,51,48,50,98,51,113,62,62,62,4,4,53,124,188,1,210,52,2,236,11,32,42, +154,32,38,2,58,47,20,29,90,150,153,88,88,9,11,19,96,24,24,64,63,230,64,4,3,98,138,106,0,0,0,2,1,58,2,140,3,151,6,3,0,26,0,41,0,0,1,30,1,21,20,6,35,34,38,53,52,54,51,50,22,23,46,1,39,7,39,55,39,51,23,55,23,3,46,1,35,34,6,21,20,22,51,50,54,53,52,38,2,168, +124,115,159,144,143,159,159,141,21,22,10,21,46,24,175,19,149,115,138,80,183,20,109,22,52,28,92,97,94,85,86,94,37,5,131,119,212,112,150,166,166,150,148,166,1,1,25,50,24,51,55,44,112,81,53,55,254,238,7,8,118,111,110,119,119,110,61,114,0,1,1,79,2,144,3, +130,5,30,0,40,0,0,1,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,2,209,84,93,174,161,53,115,60,47,115,63,109,114,106,95,99,104,85,91,94,87,47,109,66,67,115,50,133,153,82,3,240,13,83,61, +93,102,15,16,97,19,20,59,55,45,62,81,48,34,42,48,14,15,93,14,13,88,75,53,72,0,1,1,87,2,156,3,122,6,3,0,19,0,0,1,21,35,34,6,29,1,51,21,35,17,35,17,35,53,51,53,52,54,51,3,122,132,62,49,243,243,116,188,188,107,113,6,3,85,46,57,56,80,253,221,2,35,80,44,103, +97,0,0,0,0,1,1,98,1,173,3,111,5,15,0,23,0,0,1,53,51,17,35,53,33,17,51,21,35,21,20,7,6,43,1,53,51,50,55,54,61,1,1,206,153,200,1,60,148,148,57,56,104,160,147,57,28,29,2,156,92,1,199,80,253,233,92,11,109,59,60,88,35,35,70,11,0,2,1,71,1,166,3,138,5,13,0, +10,0,36,0,0,1,48,53,39,34,6,20,22,51,50,54,23,20,6,35,34,38,39,53,30,1,51,50,54,61,2,14,1,35,34,38,53,52,54,51,33,3,22,166,85,90,90,86,80,85,116,150,145,48,105,52,62,100,43,93,86,28,95,69,124,147,145,126,1,52,3,219,119,117,120,232,122,122,163,141,145, +15,15,102,25,25,91,98,5,70,53,51,175,148,127,179,0,0,1,1,91,1,171,3,118,5,14,0,19,0,0,1,17,51,17,20,22,51,50,54,53,17,51,17,35,17,14,1,35,34,38,1,91,116,67,71,82,87,116,116,31,107,71,108,106,3,137,1,133,254,123,84,80,103,96,1,98,252,157,1,79,54,56,126, +0,0,2,1,67,2,156,3,142,6,3,0,3,0,21,0,0,1,51,21,35,7,33,17,51,21,35,21,51,21,33,53,51,53,35,53,51,53,35,2,52,116,116,181,1,41,223,223,230,253,192,230,241,241,181,6,3,130,114,254,230,92,173,80,80,173,92,202,0,0,1,1,97,2,156,3,112,5,15,0,13,0,0,1,35,34, +38,53,17,35,53,33,17,6,22,59,1,3,112,129,104,113,181,1,41,1,57,57,117,2,156,117,110,1,64,80,254,112,70,70,0,0,1,1,73,2,156,3,136,5,15,0,11,0,0,1,33,21,35,17,51,21,33,53,51,17,35,1,73,2,63,230,230,253,193,230,230,5,15,80,254,45,80,80,1,211,0,0,0,0,1,1, +71,2,156,3,138,5,15,0,19,0,0,1,21,35,21,51,21,33,53,51,53,35,53,51,53,35,53,33,21,35,21,3,138,232,230,253,193,230,232,232,230,2,63,230,3,245,92,173,80,80,173,92,202,80,80,202,0,0,3,1,100,1,173,3,109,6,3,0,3,0,18,0,28,0,0,1,51,21,35,3,34,53,52,59,1,17, +51,17,51,21,35,6,7,6,39,48,35,34,23,22,51,50,55,54,2,135,116,116,100,191,170,121,116,114,120,12,33,51,21,114,74,1,3,77,66,24,11,6,3,130,252,44,124,115,2,115,253,141,87,63,35,53,152,29,36,27,13,0,0,0,1,1,85,1,173,3,124,6,10,0,13,0,0,1,20,22,59,1,21,35, +34,38,53,17,35,53,33,2,131,57,56,136,147,100,118,186,1,46,2,145,70,70,88,116,112,3,40,81,0,0,0,0,1,1,85,1,173,3,124,6,10,0,25,0,0,1,20,22,59,1,21,20,7,6,43,1,53,51,50,55,54,61,1,35,34,38,53,17,35,53,33,2,131,57,56,136,56,57,104,129,116,57,29,27,30,104, +114,186,1,46,3,127,69,71,98,109,59,60,88,35,34,71,11,119,108,2,58,81,0,0,0,0,1,1,126,2,156,3,83,5,30,0,5,0,0,1,51,17,33,21,33,1,126,128,1,85,254,43,5,30,253,221,95,0,1,1,37,1,173,3,171,5,30,0,48,0,0,1,62,1,51,50,23,22,21,17,21,20,7,6,43,1,53,51,50,55, +54,61,1,49,17,52,38,35,34,6,21,17,35,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,22,2,138,22,66,46,86,34,35,50,51,95,117,106,51,26,25,34,44,50,37,106,36,47,46,36,105,105,21,62,40,48,64,4,207,41,38,58,59,162,254,221,83,109,59,60,88,35,34,71,11,1,103, +133,64,69,128,254,153,1,103,134,63,69,128,254,153,2,115,54,34,35,39,0,0,1,1,37,1,171,3,172,5,30,0,34,0,0,1,14,1,35,34,38,53,17,51,17,20,22,51,50,54,53,17,51,17,20,22,51,50,54,53,17,51,17,35,17,14,1,35,34,38,2,70,21,66,47,85,70,106,34,44,50,37,106,36, +47,46,35,106,106,20,63,39,48,64,2,235,40,39,117,162,1,107,254,153,132,65,69,128,1,103,254,153,134,63,69,128,1,103,252,141,1,54,34,35,39,0,1,1,85,1,173,3,124,5,30,0,27,0,0,1,20,6,43,1,53,51,50,54,53,17,51,21,62,1,51,50,22,21,17,35,17,52,38,35,34,6,21, +2,24,77,85,33,23,49,36,88,31,84,56,91,93,86,59,59,70,81,2,145,120,108,88,54,86,2,126,97,56,56,134,129,254,133,1,119,89,89,107,92,0,0,1,1,85,1,173,3,124,5,30,0,36,0,0,1,53,17,52,39,38,35,34,7,6,21,17,35,17,51,21,54,55,54,51,50,23,22,21,17,29,1,20,22,59, +1,21,35,34,39,38,53,2,185,29,30,58,71,40,41,87,87,31,42,43,55,91,47,47,36,49,23,33,85,38,39,2,156,72,1,47,89,44,45,53,54,92,254,158,2,115,97,56,28,28,66,68,129,254,205,72,11,86,54,88,54,54,120,0,0,1,1,63,2,156,3,146,5,30,0,9,0,0,1,51,1,17,51,17,35,1, +17,35,1,63,171,1,45,123,171,254,211,123,5,30,254,7,1,249,253,126,1,250,254,6,0,0,0,3,1,58,2,140,3,151,5,30,0,14,0,23,0,32,0,0,0,32,23,22,21,20,7,6,35,34,39,38,53,52,55,23,34,7,6,7,33,38,39,38,19,33,22,23,22,51,50,55,54,1,213,1,38,78,78,78,77,148,147, +77,78,78,224,88,45,40,5,1,101,5,40,45,87,254,161,9,33,45,88,89,45,33,5,30,84,85,160,161,84,84,84,84,161,160,85,3,61,53,99,99,53,61,254,207,74,44,61,61,44,0,0,3,1,58,1,174,3,151,6,3,0,29,0,38,0,47,0,0,1,35,53,33,21,35,21,22,23,22,21,20,7,6,7,21,51,21, +33,53,51,53,38,39,38,53,52,55,54,55,23,17,54,55,54,53,52,39,38,3,17,6,7,6,21,20,23,22,2,51,151,1,162,151,102,60,78,78,60,102,151,254,94,151,108,63,78,78,63,108,116,44,27,46,46,27,160,50,30,46,46,30,5,167,92,92,141,15,65,85,160,161,84,65,15,134,92,92, +133,13,68,84,161,160,85,68,13,93,254,47,14,37,62,119,120,61,37,254,59,1,214,13,41,61,120,119,62,41,0,0,0,1,1,91,1,173,3,118,5,30,0,60,0,0,1,21,46,1,35,34,7,6,21,20,23,22,31,1,22,23,22,21,20,7,6,35,34,47,1,21,20,22,59,1,21,35,34,39,38,61,3,22,23,22,51, +50,54,53,52,39,38,47,1,46,1,53,52,55,54,51,50,23,22,3,80,49,106,56,87,42,44,31,31,93,40,123,52,52,77,78,137,56,62,13,48,66,147,160,114,51,52,64,62,63,61,82,88,31,33,107,41,107,96,70,71,130,64,57,56,4,253,98,23,22,23,24,47,36,21,20,18,8,24,43,42,77,87, +51,51,9,3,7,86,54,88,54,54,120,34,49,57,29,15,15,50,45,42,23,22,21,8,20,84,73,88,48,48,8,8,0,0,0,0,1,1,120,1,173,3,89,6,3,0,20,0,0,1,2,3,52,54,59,1,21,35,34,6,21,19,20,6,43,1,53,51,50,54,2,9,1,1,106,123,109,111,62,49,2,103,114,44,31,66,48,2,145,1,93, +1,77,101,99,85,45,58,253,74,120,108,88,54,0,0,0,0,1,1,77,1,173,3,132,5,193,0,33,0,0,1,21,33,21,33,17,20,23,22,59,1,21,20,7,6,43,1,53,51,50,55,54,61,1,35,34,39,38,53,17,35,53,51,53,2,125,1,7,254,249,30,29,74,130,56,56,104,130,117,57,28,28,25,131,53,54, +188,188,5,193,178,80,254,172,70,27,28,93,109,59,60,88,35,34,71,11,46,47,114,1,84,80,178,0,0,0,0,2,0,208,2,140,4,1,5,15,0,23,0,33,0,0,19,53,51,17,51,17,33,17,51,17,51,21,35,21,35,53,6,7,6,35,34,38,61,1,41,1,21,20,23,22,51,50,55,54,208,109,116,1,103,116, +117,117,116,42,56,55,74,122,126,1,219,254,153,39,39,78,94,55,49,3,153,92,1,26,254,230,1,26,254,230,92,253,96,57,28,27,134,130,5,2,89,44,45,54,47,0,0,0,0,1,1,32,2,139,3,177,5,15,0,29,0,0,1,53,33,21,14,1,21,20,22,50,54,53,52,38,39,53,33,21,35,30,1,21,20, +6,32,38,53,52,54,55,1,32,1,22,68,82,111,182,111,87,63,1,19,149,72,69,178,254,228,179,66,75,4,179,92,123,39,121,75,89,109,109,89,82,118,35,123,92,56,125,76,131,164,163,128,82,121,58,0,1,1,70,2,156,3,139,5,15,0,26,0,0,1,51,49,30,1,21,20,6,43,1,34,38,53, +17,51,17,20,22,63,1,50,54,53,52,38,39,38,2,51,203,72,69,179,141,45,114,102,116,49,65,32,91,110,91,58,48,4,196,56,125,76,131,164,108,119,1,144,254,112,85,56,1,1,109,89,81,123,31,24,0,0,1,1,17,2,156,3,192,5,15,0,6,0,0,1,35,11,1,35,1,51,3,192,123,221,220, +123,1,9,157,2,156,2,14,253,242,2,115,0,0,0,1,1,97,2,156,3,112,5,16,0,9,0,0,1,33,21,1,33,21,33,53,1,33,1,112,2,0,254,107,1,149,253,241,1,149,254,122,5,16,94,254,62,84,95,1,195,0,0,1,1,94,1,173,3,115,5,15,0,22,0,0,1,33,21,1,33,21,35,21,20,22,59,1,21,35, +34,39,38,61,1,33,53,1,33,1,106,1,157,254,185,1,71,1,36,50,23,33,86,38,39,254,175,1,71,254,197,5,15,94,254,61,82,11,86,54,88,54,54,120,11,94,1,195,0,2,1,77,2,94,3,132,5,15,0,20,0,28,0,0,1,6,21,35,52,55,35,53,1,33,53,33,21,1,51,54,51,50,21,22,35,39,48, +51,50,53,52,35,6,2,146,2,97,3,229,1,180,254,92,2,39,254,76,110,38,138,143,1,210,13,13,109,44,56,2,156,29,33,33,29,94,1,195,82,94,254,61,162,138,106,82,31,51,1,0,0,0,1,1,51,1,168,3,158,5,15,0,28,0,0,1,50,23,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53, +52,38,43,1,53,1,33,53,33,21,2,100,67,80,62,105,191,177,59,125,67,53,126,68,120,126,117,104,110,1,15,254,92,2,39,3,167,32,23,120,77,124,135,21,20,109,27,28,84,80,74,83,93,1,24,82,94,0,0,0,3,1,58,2,140,3,151,5,228,0,6,0,13,0,24,0,0,1,46,1,35,34,6,7,5,33, +30,1,51,50,54,0,32,22,21,20,6,35,34,38,53,52,3,26,4,85,89,88,85,4,1,99,254,157,3,86,88,89,86,254,190,1,38,156,155,148,147,155,4,108,126,162,162,126,103,126,163,163,2,93,220,208,209,219,219,209,208,255,255,0,37,254,10,4,172,5,213,16,38,2,173,0,0,16,6, +0,36,0,0,0,0,255,255,0,133,254,10,4,35,4,123,16,38,2,173,0,0,16,6,0,68,0,0,0,0,255,255,0,166,0,0,4,113,7,80,16,38,13,7,0,0,16,6,0,37,0,0,0,0,255,255,0,193,255,227,4,88,6,20,16,38,2,143,50,0,16,6,0,69,0,0,0,0,255,255,0,166,254,99,4,113,5,213,16,38,2,171, +0,0,16,6,0,37,0,0,0,0,255,255,0,193,254,99,4,88,6,20,16,38,2,171,0,0,16,6,0,69,0,0,0,0,255,255,0,166,254,155,4,113,5,213,16,38,2,185,0,0,16,6,0,37,0,0,0,0,255,255,0,193,254,155,4,88,6,20,16,38,2,185,0,0,16,6,0,69,0,0,0,0,255,255,0,139,254,117,4,49,7, +107,16,39,12,255,0,90,1,117,16,38,2,175,100,0,16,6,0,38,0,0,0,0,255,255,0,195,254,117,4,37,6,102,16,38,0,118,90,0,16,38,2,175,104,0,16,6,0,70,0,0,255,255,0,137,0,0,4,82,7,80,16,38,13,7,206,0,16,6,0,39,0,0,0,0,255,255,0,123,255,227,4,18,6,20,16,38,2,143, +206,0,16,6,0,71,0,0,0,0,255,255,0,137,254,99,4,82,5,213,16,38,2,171,206,0,16,6,0,39,0,0,0,0,255,255,0,123,254,99,4,18,6,20,16,38,2,171,0,0,16,6,0,71,0,0,0,0,255,255,0,137,254,155,4,82,5,213,16,38,2,185,206,0,16,6,0,39,0,0,0,0,255,255,0,123,254,155,4, +18,6,20,16,38,2,185,0,0,16,6,0,71,0,0,0,0,255,255,0,125,254,117,4,82,5,213,16,39,2,175,254,242,0,0,18,6,0,39,0,0,255,255,0,123,254,117,4,18,6,20,16,38,2,175,236,0,18,6,0,71,0,0,0,0,255,255,0,137,254,27,4,82,5,213,16,38,2,181,206,0,16,6,0,39,0,0,0,0,255, +255,0,123,254,27,4,18,6,20,16,38,2,181,0,0,16,6,0,71,0,0,0,0,255,255,0,197,254,27,4,78,5,213,16,38,2,181,18,0,16,6,0,40,0,0,0,0,255,255,0,123,254,27,4,88,4,123,16,38,2,181,14,0,16,6,0,72,0,0,0,0,255,255,0,197,254,27,4,78,5,213,16,38,2,184,18,0,16,6,0, +40,0,0,0,0,255,255,0,123,254,27,4,88,4,123,16,38,2,184,14,0,16,6,0,72,0,0,0,0,255,255,0,197,254,117,4,78,7,109,16,38,13,6,18,0,16,38,0,40,0,0,16,6,2,175,50,0,255,255,0,123,254,117,4,88,6,72,16,38,2,142,14,0,16,38,0,72,0,0,16,6,2,175,50,0,255,255,0,233, +0,0,4,88,7,80,16,38,13,7,54,0,16,6,0,41,0,0,0,0,255,255,0,195,0,0,4,39,7,80,16,38,13,7,0,0,16,6,0,73,0,0,0,0,255,255,0,102,255,227,4,80,7,48,16,38,13,11,50,0,16,6,0,42,0,0,0,0,255,255,0,123,254,72,4,18,5,246,16,38,2,140,0,0,16,6,0,74,0,0,0,0,255,255, +0,137,0,0,4,72,7,80,16,38,13,7,0,0,16,6,0,43,0,0,0,0,255,255,0,195,0,0,4,27,7,80,16,38,13,7,0,0,16,6,0,75,0,0,0,0,255,255,0,137,254,99,4,72,5,213,16,38,2,171,0,0,16,6,0,43,0,0,0,0,255,255,0,195,254,99,4,27,6,20,16,38,2,171,0,0,16,6,0,75,0,0,0,0,255,255, +0,137,0,0,4,72,7,53,16,39,12,254,0,0,1,92,18,6,0,43,0,0,255,255,0,195,0,0,4,27,7,88,16,39,0,106,0,7,1,72,18,6,0,75,0,0,255,255,0,20,254,117,4,72,5,213,16,39,2,175,254,137,0,0,16,6,0,43,0,0,255,255,0,55,254,117,4,27,6,20,16,39,2,175,254,172,0,0,16,6,0, +75,0,0,255,255,0,137,254,25,4,72,5,213,16,38,2,182,0,0,16,6,0,43,0,0,0,0,255,255,0,195,254,25,4,27,6,20,16,38,2,182,0,0,16,6,0,75,0,0,0,0,255,255,0,201,254,27,4,6,5,213,16,38,2,184,0,0,16,6,0,44,0,0,0,0,255,255,0,178,254,27,4,68,6,20,16,38,2,184,0,0, +16,6,0,76,0,0,0,0,255,255,0,137,0,0,4,201,7,107,16,39,12,255,0,0,1,117,16,6,0,46,0,0,255,255,0,236,0,0,4,178,7,107,16,39,12,255,255,37,1,117,16,6,0,78,0,0,255,255,0,137,254,99,4,201,5,213,16,38,2,171,0,0,16,6,0,46,0,0,0,0,255,255,0,236,254,99,4,178,6, +20,16,38,2,171,50,0,16,6,0,78,0,0,0,0,255,255,0,137,254,155,4,201,5,213,16,38,2,185,0,0,16,6,0,46,0,0,0,0,255,255,0,236,254,155,4,178,6,20,16,38,2,185,50,0,16,6,0,78,0,0,0,0,255,255,0,215,254,99,4,115,5,213,16,38,2,171,50,0,16,6,0,47,0,0,0,0,255,255, +0,160,254,99,4,10,6,31,16,38,2,171,0,0,16,6,0,79,0,0,0,0,255,255,0,215,254,99,4,115,7,48,16,38,13,11,0,0,16,6,5,161,0,0,0,0,255,255,0,160,254,99,4,10,7,48,16,38,13,11,0,0,16,6,5,162,0,0,0,0,255,255,0,215,254,155,4,115,5,213,16,38,2,185,50,0,16,6,0,47, +0,0,0,0,255,255,0,160,254,155,4,10,6,31,16,38,2,185,0,0,16,6,0,79,0,0,0,0,255,255,0,215,254,27,4,115,5,213,16,38,2,181,50,0,16,6,0,47,0,0,0,0,255,255,0,160,254,27,4,10,6,31,16,38,2,181,0,0,16,6,0,79,0,0,0,0,255,255,0,86,0,0,4,121,7,107,16,39,12,255,0, +0,1,117,16,6,0,48,0,0,255,255,0,109,0,0,4,111,6,102,16,38,0,118,0,0,16,6,0,80,0,0,0,0,255,255,0,86,0,0,4,121,7,80,16,38,13,7,0,0,16,6,0,48,0,0,0,0,255,255,0,109,0,0,4,111,6,16,16,38,2,143,0,0,18,6,0,80,0,0,0,0,255,255,0,86,254,99,4,121,5,213,16,38,2, +171,0,0,16,6,0,48,0,0,0,0,255,255,0,109,254,99,4,111,4,123,16,38,2,171,0,0,16,6,0,80,0,0,0,0,255,255,0,139,0,0,4,70,7,80,16,38,13,7,0,0,16,6,0,49,0,0,0,0,255,255,0,195,0,0,4,27,6,16,16,38,2,143,0,0,16,6,0,81,0,0,0,0,255,255,0,139,254,99,4,70,5,213,16, +38,2,171,0,0,16,6,0,49,0,0,0,0,255,255,0,195,254,99,4,27,4,123,16,38,2,171,0,0,16,6,0,81,0,0,0,0,255,255,0,139,254,155,4,70,5,213,16,38,2,185,0,0,16,6,0,49,0,0,0,0,255,255,0,195,254,155,4,27,4,123,16,38,2,185,0,0,16,6,0,81,0,0,0,0,255,255,0,139,254,27, +4,70,5,213,16,38,2,181,0,0,16,6,0,49,0,0,0,0,255,255,0,195,254,27,4,27,4,123,16,38,2,181,0,0,16,6,0,81,0,0,0,0,255,255,0,117,255,227,4,92,7,249,16,38,0,50,0,0,16,39,13,0,0,0,1,6,16,7,12,255,0,50,2,3,255,255,0,137,255,227,4,72,7,250,16,39,2,137,0,0,1, +148,16,38,0,82,0,0,16,6,2,121,0,0,0,0,255,255,0,197,0,0,4,117,7,114,16,39,12,255,255,119,1,124,18,6,0,51,0,0,255,255,0,190,254,86,4,84,6,102,16,38,2,137,0,0,18,6,0,83,0,0,0,0,255,255,0,197,0,0,4,117,7,80,16,38,13,7,0,0,16,6,0,51,0,0,0,0,255,255,0,190, +254,86,4,84,6,16,16,38,2,143,0,0,18,6,0,83,0,0,0,0,255,255,0,143,0,0,4,209,7,80,16,38,13,7,206,0,16,6,0,53,0,0,0,0,255,255,1,106,0,0,4,131,6,16,16,38,2,143,0,0,16,6,0,85,0,0,0,0,255,255,0,143,254,99,4,209,5,213,16,38,2,171,206,0,16,6,0,53,0,0,0,0,255, +255,1,106,254,99,4,131,4,123,16,38,2,171,0,0,16,6,0,85,0,0,0,0,255,255,0,143,254,99,4,209,7,48,16,38,13,11,206,0,16,6,5,191,0,0,0,0,255,255,1,61,254,99,4,131,5,246,16,38,2,140,0,0,16,6,5,192,0,0,0,0,255,255,0,143,254,155,4,209,5,213,16,38,2,185,0,0,16, +6,0,53,0,0,0,0,255,255,1,61,254,155,4,131,4,123,16,38,2,185,0,0,16,6,0,85,0,0,0,0,255,255,0,139,255,227,4,74,7,80,16,38,13,7,0,0,16,6,0,54,0,0,0,0,255,255,0,213,255,227,4,6,6,16,16,38,2,143,0,0,18,6,0,86,0,0,0,0,255,255,0,139,254,99,4,74,5,240,16,38, +2,171,0,0,16,6,0,54,0,0,0,0,255,255,0,213,254,99,4,6,4,123,16,38,2,171,0,0,16,6,0,86,0,0,0,0,255,255,0,139,254,99,4,74,7,80,16,38,13,7,0,0,16,38,0,54,0,0,16,6,2,171,0,0,255,255,0,213,254,99,4,6,6,16,16,38,2,143,0,0,16,38,0,86,0,0,16,6,2,171,0,0,255,255, +0,47,0,0,4,162,7,80,16,38,13,7,0,0,16,6,0,55,0,0,0,0,255,255,0,131,0,0,4,8,7,80,16,38,13,7,0,0,16,6,0,87,0,0,0,0,255,255,0,47,254,99,4,162,5,213,16,38,2,171,0,0,16,6,0,55,0,0,0,0,255,255,0,131,254,99,4,8,5,158,16,38,2,171,0,0,16,6,0,87,0,0,0,0,255,255, +0,47,254,155,4,162,5,213,16,38,2,185,0,0,16,6,0,55,0,0,0,0,255,255,0,131,254,155,4,8,5,158,16,38,2,185,0,0,16,6,0,87,0,0,0,0,255,255,0,47,254,27,4,162,5,213,16,38,2,181,0,0,16,6,0,55,0,0,0,0,255,255,0,131,254,27,4,8,5,158,16,38,2,181,0,0,16,6,0,87,0, +0,0,0,255,255,0,147,254,100,4,61,5,213,16,38,2,172,0,0,16,6,0,56,0,0,0,0,255,255,0,195,254,100,4,27,4,94,16,38,2,172,0,0,16,6,0,88,0,0,0,0,255,255,0,147,254,27,4,61,5,213,16,38,2,184,0,0,16,6,0,56,0,0,0,0,255,255,0,195,254,27,4,27,4,94,16,38,2,184,0, +0,16,6,0,88,0,0,0,0,255,255,0,147,254,27,4,61,5,213,16,38,2,181,0,0,16,6,0,56,0,0,0,0,255,255,0,195,254,27,4,27,4,94,16,38,2,181,0,0,16,6,0,88,0,0,0,0,255,255,0,147,255,227,4,61,7,249,16,39,13,0,0,0,1,6,16,39,12,255,0,50,2,3,16,6,0,56,0,0,255,255,0,195, +255,227,4,27,7,250,16,39,2,137,0,0,1,148,16,38,2,121,0,0,16,6,0,88,0,0,0,0,255,255,0,57,0,0,4,152,7,69,16,39,13,0,0,0,1,92,18,6,0,57,0,0,255,255,0,100,0,0,4,109,6,15,16,38,2,121,0,216,18,6,0,89,0,0,0,0,255,255,0,57,254,99,4,152,5,213,16,38,2,171,0,0, +16,6,0,57,0,0,0,0,255,255,0,100,254,99,4,109,4,96,16,38,2,171,0,0,16,6,0,89,0,0,0,0,255,255,0,0,0,0,4,209,7,114,16,39,13,1,0,0,1,124,16,6,0,58,0,0,255,255,0,0,0,0,4,209,6,109,16,38,0,67,192,7,16,6,0,90,0,0,0,0,255,255,0,0,0,0,4,209,7,114,16,39,12,255, +0,0,1,124,16,6,0,58,0,0,255,255,0,0,0,0,4,209,6,109,16,38,0,118,64,7,16,6,0,90,0,0,0,0,255,255,0,0,0,0,4,209,7,52,16,39,0,106,0,0,1,36,16,6,0,58,0,0,255,255,0,0,0,0,4,209,5,191,16,38,0,106,0,175,16,6,0,90,0,0,0,0,255,255,0,0,0,0,4,209,7,80,16,38,13,7, +0,0,16,6,0,58,0,0,0,0,255,255,0,0,0,0,4,209,6,16,16,38,2,143,0,0,16,6,0,90,0,0,0,0,255,255,0,0,254,99,4,209,5,213,16,38,2,171,0,0,16,6,0,58,0,0,0,0,255,255,0,0,254,99,4,209,4,96,16,38,2,171,0,0,16,6,0,90,0,0,0,0,255,255,0,18,0,0,4,190,7,80,16,38,13,7, +0,0,16,6,0,59,0,0,0,0,255,255,0,76,0,0,4,133,6,16,16,38,2,143,0,0,16,6,0,91,0,0,0,0,255,255,0,18,0,0,4,190,7,53,16,39,12,254,0,18,1,92,18,6,0,59,0,0,255,255,0,76,0,0,4,133,5,191,16,38,0,106,0,175,18,6,0,91,0,0,0,0,255,255,0,37,0,0,4,172,7,80,16,38,13, +7,0,0,16,6,0,60,0,0,0,0,255,255,0,104,254,86,4,129,6,16,16,38,2,143,0,0,16,6,0,92,0,0,0,0,255,255,0,156,0,0,4,145,7,116,16,39,13,2,0,46,1,124,18,6,0,61,0,0,255,255,0,203,0,0,4,16,6,109,16,38,2,103,17,7,18,6,0,93,0,0,0,0,255,255,0,156,254,99,4,145,5,213, +16,38,2,171,50,0,18,6,0,61,0,0,0,0,255,255,0,203,254,99,4,16,4,98,16,38,2,171,0,0,18,6,0,93,0,0,0,0,255,255,0,156,254,155,4,145,5,213,16,38,2,185,50,0,16,6,0,61,0,0,0,0,255,255,0,203,254,155,4,16,4,98,16,38,2,185,0,0,16,6,0,93,0,0,0,0,255,255,0,195,254, +155,4,27,6,20,16,38,2,185,0,0,16,6,0,75,0,0,0,0,255,255,0,131,0,0,4,8,6,226,16,39,0,106,255,162,0,210,18,6,0,87,0,0,255,255,0,0,0,0,4,209,7,26,16,38,2,119,0,20,18,6,0,90,0,0,0,0,255,255,0,104,254,86,4,129,7,26,16,38,2,119,12,20,18,6,0,92,0,0,0,0,255, +255,0,195,0,0,4,39,7,80,16,38,13,7,0,0,16,6,1,65,0,0,0,0,255,255,0,137,255,227,4,72,6,34,16,6,3,2,0,0,255,255,0,37,254,99,4,172,5,213,16,38,2,171,0,0,16,6,0,36,0,0,0,0,255,255,0,133,254,99,4,35,4,123,16,38,2,171,0,0,16,6,0,68,0,0,0,0,255,255,0,37,254, +99,4,172,7,116,16,39,13,2,0,0,1,124,18,6,5,251,0,0,255,255,0,133,254,99,4,35,6,109,16,38,2,103,232,7,18,6,5,252,0,0,0,0,255,255,0,37,0,0,4,172,7,249,16,38,13,6,0,128,16,38,0,36,0,0,16,7,13,1,0,0,2,3,0,0,255,255,0,133,255,227,4,35,7,162,16,39,2,136,0, +0,1,60,18,6,0,197,0,0,255,255,0,37,254,99,4,172,7,109,16,38,13,6,0,0,18,6,5,251,0,0,0,0,255,255,0,133,254,99,4,35,6,20,16,38,2,117,232,204,18,6,5,252,0,0,0,0,255,255,0,197,254,99,4,78,5,213,16,38,2,171,18,0,16,6,0,40,0,0,0,0,255,255,0,123,254,99,4,88, +4,123,16,38,2,171,14,0,16,6,0,72,0,0,0,0,255,255,0,197,0,0,4,78,7,94,16,39,13,0,0,42,1,117,16,6,0,40,0,0,255,255,0,123,255,227,4,88,6,55,16,38,2,121,0,0,16,6,0,72,0,0,0,0,255,255,0,197,254,99,4,78,7,116,16,39,13,2,0,24,1,124,18,6,6,3,0,0,255,255,0,123, +254,99,4,88,6,109,16,38,2,103,34,7,18,6,6,4,0,0,0,0,255,255,0,201,254,99,4,6,5,213,16,38,2,171,0,0,16,6,0,44,0,0,0,0,255,255,0,178,254,99,4,68,6,20,16,38,2,171,0,0,16,6,0,76,0,0,0,0,255,255,0,117,254,99,4,92,5,240,16,38,2,171,0,0,16,6,0,50,0,0,0,0,255, +255,0,137,254,99,4,72,4,123,16,38,2,171,0,0,16,6,0,82,0,0,0,0,255,255,0,117,254,99,4,92,7,116,16,39,13,2,0,0,1,124,18,6,6,11,0,0,255,255,0,137,254,99,4,72,6,109,16,38,2,103,0,7,18,6,6,12,0,0,0,0,255,255,0,6,255,227,4,167,7,107,16,39,12,255,255,145,1, +117,18,6,1,98,0,0,255,255,0,32,255,227,4,178,6,102,16,38,0,118,151,0,18,6,1,99,0,0,0,0,255,255,0,6,255,227,4,167,7,107,16,39,13,1,255,145,1,117,18,6,1,98,0,0,255,255,0,32,255,227,4,178,6,102,16,38,0,67,151,0,18,6,1,99,0,0,0,0,255,255,0,6,255,227,4,167, +7,94,16,39,13,0,255,145,1,117,18,6,1,98,0,0,255,255,0,32,255,227,4,178,6,55,16,38,2,121,151,0,18,6,1,99,0,0,0,0,255,255,0,6,254,99,4,167,6,21,16,38,2,171,145,0,18,6,1,98,0,0,0,0,255,255,0,32,254,99,4,178,4,123,16,38,2,171,151,0,18,6,1,99,0,0,0,0,255, +255,0,147,254,99,4,61,5,213,16,38,2,171,0,0,16,6,0,56,0,0,0,0,255,255,0,195,254,99,4,27,4,94,16,38,2,171,0,0,16,6,0,88,0,0,0,0,255,255,0,9,255,227,4,200,7,107,16,39,12,255,255,118,1,117,18,6,1,113,0,0,255,255,0,39,255,227,4,170,6,102,16,39,0,118,255, +100,0,0,18,6,1,114,0,0,255,255,0,9,255,227,4,200,7,107,16,39,13,1,255,118,1,117,18,6,1,113,0,0,255,255,0,39,255,227,4,170,6,102,16,39,0,67,255,100,0,0,18,6,1,114,0,0,255,255,0,9,255,227,4,200,7,94,16,39,13,0,255,118,1,117,18,6,1,113,0,0,255,255,0,39, +255,227,4,170,6,55,16,39,2,121,255,100,0,0,18,6,1,114,0,0,255,255,0,9,254,99,4,200,6,25,16,39,2,171,255,118,0,0,18,6,1,113,0,0,255,255,0,39,254,99,4,170,4,113,16,39,2,171,255,100,0,0,18,6,1,114,0,0,255,255,0,37,0,0,4,172,7,114,16,39,13,1,0,0,1,124,16, +6,0,60,0,0,255,255,0,104,254,86,4,129,6,109,16,38,0,67,204,7,16,6,0,92,0,0,0,0,255,255,0,37,254,99,4,172,5,213,16,38,2,171,0,0,16,6,0,60,0,0,0,0,255,255,0,104,254,86,4,129,4,96,16,39,2,171,0,250,0,0,16,6,0,92,0,0,255,255,0,37,0,0,4,172,7,94,16,39,13, +0,0,0,1,117,16,6,0,60,0,0,255,255,0,104,254,86,4,129,6,55,16,38,2,121,0,0,16,6,0,92,0,0,0,0,255,255,0,70,255,231,4,149,6,114,16,38,2,255,0,0,16,6,6,215,0,0,0,0,255,255,0,70,255,231,4,149,6,114,16,38,2,255,0,0,16,6,7,15,0,0,0,0,255,255,0,70,255,231,4, +149,6,114,16,38,2,255,0,0,16,6,6,228,0,0,0,0,255,255,0,70,255,231,4,149,6,114,16,38,2,255,0,0,16,6,6,241,0,0,0,0,255,255,0,70,255,231,4,149,6,114,16,38,2,255,0,0,16,6,6,229,0,0,0,0,255,255,0,70,255,231,4,149,6,114,16,38,2,255,0,0,16,6,6,242,0,0,0,0,255, +255,0,70,255,231,4,149,7,209,16,38,2,255,0,0,16,6,6,230,0,0,0,0,255,255,0,70,255,231,4,149,7,209,16,38,2,255,0,0,16,6,6,243,0,0,0,0,255,255,0,37,0,0,4,172,6,114,16,38,2,224,0,0,16,7,6,215,254,162,0,0,255,255,0,37,0,0,4,172,6,114,16,38,2,224,0,0,16,7, +7,15,254,112,0,0,255,255,254,107,0,0,4,172,6,114,16,38,2,224,0,0,16,7,6,228,253,118,0,0,255,255,254,107,0,0,4,172,6,114,16,38,2,224,0,0,16,7,6,241,253,118,0,0,255,255,255,26,0,0,4,172,6,114,16,38,2,224,0,0,16,7,6,229,253,243,0,0,255,255,255,6,0,0,4,172, +6,114,16,38,2,224,0,0,16,7,6,242,253,243,0,0,255,255,255,193,0,0,4,172,7,209,16,38,2,224,0,0,16,7,6,230,254,162,0,0,255,255,255,143,0,0,4,172,7,209,16,38,2,224,0,0,16,7,6,243,254,112,0,0,255,255,0,169,255,234,4,40,6,114,16,38,3,3,0,0,16,6,6,215,0,0,0, +0,255,255,0,169,255,234,4,40,6,114,16,38,3,3,0,0,16,6,7,15,0,0,0,0,255,255,0,169,255,234,4,40,6,114,16,38,3,3,0,0,16,6,6,228,0,0,0,0,255,255,0,169,255,234,4,40,6,114,16,38,3,3,0,0,16,6,6,241,0,0,0,0,255,255,0,169,255,234,4,40,6,114,16,38,3,3,0,0,16,6, +6,229,0,0,0,0,255,255,0,169,255,234,4,40,6,114,16,38,3,3,0,0,16,6,6,242,0,0,0,0,255,255,255,126,0,0,4,78,6,114,16,38,2,228,0,0,16,7,6,215,253,143,0,0,255,255,255,126,0,0,4,78,6,114,16,38,2,228,0,0,16,7,7,15,253,143,0,0,255,255,253,138,0,0,4,78,6,114, +16,38,2,228,0,0,16,7,6,228,252,149,0,0,255,255,253,138,0,0,4,78,6,114,16,38,2,228,0,0,16,7,6,241,252,149,0,0,255,255,254,7,0,0,4,78,6,114,16,38,2,228,0,0,16,7,6,229,252,224,0,0,255,255,253,243,0,0,4,78,6,114,16,38,2,228,0,0,16,7,6,242,252,224,0,0,255, +255,0,195,254,86,4,27,6,114,16,38,3,5,0,0,16,6,6,215,0,0,0,0,255,255,0,195,254,86,4,27,6,114,16,38,3,5,0,0,16,6,7,15,0,0,0,0,255,255,0,195,254,86,4,27,6,114,16,38,3,5,0,0,16,6,6,228,0,0,0,0,255,255,0,195,254,86,4,27,6,114,16,38,3,5,0,0,16,6,6,241,0,0, +0,0,255,255,0,195,254,86,4,30,6,114,16,38,3,5,0,0,16,6,6,229,0,0,0,0,255,255,0,195,254,86,4,30,6,114,16,38,3,5,0,0,16,6,6,242,0,0,0,0,255,255,0,195,254,86,4,27,7,209,16,38,3,5,0,0,16,6,6,230,0,0,0,0,255,255,0,195,254,86,4,27,7,209,16,38,3,5,0,0,16,6, +6,243,0,0,0,0,255,255,255,76,0,0,4,72,6,114,16,38,2,230,0,0,16,7,6,215,253,93,0,0,255,255,255,76,0,0,4,72,6,114,16,38,2,230,0,0,16,7,7,15,253,93,0,0,255,255,253,63,0,0,4,72,6,114,16,38,2,230,0,0,16,7,6,228,252,74,0,0,255,255,253,63,0,0,4,72,6,114,16, +38,2,230,0,0,16,7,6,241,252,74,0,0,255,255,253,163,0,0,4,72,6,114,16,38,2,230,0,0,16,7,6,229,252,124,0,0,255,255,253,143,0,0,4,72,6,114,16,38,2,230,0,0,16,7,6,242,252,124,0,0,255,255,254,99,0,0,4,72,7,209,16,38,2,230,0,0,16,7,6,230,253,68,0,0,255,255, +254,99,0,0,4,72,7,209,16,38,2,230,0,0,16,7,6,243,253,68,0,0,255,255,1,54,0,0,3,207,6,114,16,38,3,7,0,0,16,6,6,215,0,0,0,0,255,255,1,54,0,0,3,207,6,114,16,38,3,7,0,0,16,6,7,15,0,0,0,0,255,255,0,245,0,0,3,240,6,114,16,38,3,7,0,0,16,6,6,228,0,0,0,0,255, +255,0,245,0,0,3,240,6,114,16,38,3,7,0,0,16,6,6,241,0,0,0,0,255,255,1,39,0,0,4,30,6,114,16,38,3,7,0,0,16,6,6,229,0,0,0,0,255,255,1,19,0,0,4,30,6,114,16,38,3,7,0,0,16,6,6,242,0,0,0,0,255,255,1,31,0,0,3,207,7,209,16,38,3,7,0,0,16,6,6,230,0,0,0,0,255,255, +1,31,0,0,3,207,7,209,16,38,3,7,0,0,16,6,6,243,0,0,0,0,255,255,255,126,0,0,4,6,6,114,16,38,2,232,0,0,16,7,6,215,253,143,0,0,255,255,255,126,0,0,4,6,6,114,16,38,2,232,0,0,16,7,7,15,253,143,0,0,255,255,253,163,0,0,4,6,6,114,16,38,2,232,0,0,16,7,6,228,252, +174,0,0,255,255,253,163,0,0,4,6,6,114,16,38,2,232,0,0,16,7,6,241,252,174,0,0,255,255,254,7,0,0,4,6,6,114,16,38,2,232,0,0,16,7,6,229,252,224,0,0,255,255,253,243,0,0,4,6,6,114,16,38,2,232,0,0,16,7,6,242,252,224,0,0,255,255,254,174,0,0,4,6,7,209,16,38,2, +232,0,0,16,7,6,230,253,143,0,0,255,255,254,174,0,0,4,6,7,209,16,38,2,232,0,0,16,7,6,243,253,143,0,0,255,255,0,137,255,227,4,72,6,114,16,38,3,13,0,0,16,6,6,215,0,0,0,0,255,255,0,137,255,227,4,72,6,114,16,38,3,13,0,0,16,6,7,15,0,0,0,0,255,255,0,137,255, +227,4,72,6,114,16,38,3,13,0,0,16,6,6,228,0,0,0,0,255,255,0,137,255,227,4,72,6,114,16,38,3,13,0,0,16,6,6,241,0,0,0,0,255,255,0,137,255,227,4,72,6,114,16,38,3,13,0,0,16,6,6,229,0,0,0,0,255,255,0,137,255,227,4,72,6,114,16,38,3,13,0,0,16,6,6,242,0,0,0,0, +255,255,255,201,255,227,4,92,6,114,16,38,2,238,0,0,16,7,6,215,253,218,0,0,255,255,255,126,255,227,4,92,6,114,16,38,2,238,0,0,16,7,7,15,253,143,0,0,255,255,253,138,255,227,4,92,6,114,16,38,2,238,0,0,16,7,6,228,252,149,0,0,255,255,253,138,255,227,4,92, +6,114,16,38,2,238,0,0,16,7,6,241,252,149,0,0,255,255,254,157,255,227,4,92,6,114,16,38,2,238,0,0,16,7,6,229,253,118,0,0,255,255,254,137,255,227,4,92,6,114,16,38,2,238,0,0,16,7,6,242,253,118,0,0,255,255,0,51,0,0,4,105,6,114,16,38,3,19,0,0,16,6,6,215,0, +0,0,0,255,255,0,51,0,0,4,105,6,114,16,38,3,19,0,0,16,6,7,15,0,0,0,0,255,255,0,51,0,0,4,105,6,114,16,38,3,19,0,0,16,6,6,228,0,0,0,0,255,255,0,51,0,0,4,105,6,114,16,38,3,19,0,0,16,6,6,241,0,0,0,0,255,255,0,51,0,0,4,105,6,114,16,38,3,19,0,0,16,6,6,229,0, +0,0,0,255,255,0,51,0,0,4,105,6,114,16,38,3,19,0,0,16,6,6,242,0,0,0,0,255,255,0,51,0,0,4,105,7,209,16,38,3,19,0,0,16,6,6,230,0,0,0,0,255,255,0,51,0,0,4,105,7,209,16,38,3,19,0,0,16,6,6,243,0,0,0,0,255,255,254,232,0,0,4,172,6,114,16,38,2,243,0,0,16,7,7, +15,252,249,0,0,255,255,253,63,0,0,4,172,6,114,16,38,2,243,0,0,16,7,6,241,252,74,0,0,255,255,253,68,0,0,4,172,6,114,16,38,2,243,0,0,16,7,6,242,252,49,0,0,255,255,254,24,0,0,4,172,7,209,16,38,2,243,0,0,16,7,6,243,252,249,0,0,255,255,0,70,255,227,4,140, +6,114,16,38,3,23,0,0,16,6,6,215,0,0,0,0,255,255,0,70,255,227,4,140,6,114,16,38,3,23,0,0,16,6,7,15,0,0,0,0,255,255,0,70,255,227,4,140,6,114,16,38,3,23,0,0,16,6,6,228,0,0,0,0,255,255,0,70,255,227,4,140,6,114,16,38,3,23,0,0,16,6,6,241,0,0,0,0,255,255,0, +70,255,227,4,140,6,114,16,38,3,23,0,0,16,6,6,229,0,0,0,0,255,255,0,70,255,227,4,140,6,114,16,38,3,23,0,0,16,6,6,242,0,0,0,0,255,255,0,70,255,227,4,140,7,209,16,38,3,23,0,0,16,6,6,230,0,0,0,0,255,255,0,70,255,227,4,140,7,209,16,38,3,23,0,0,16,6,6,243, +0,0,0,0,255,255,255,201,0,0,4,135,6,114,16,38,2,247,0,0,16,7,6,215,253,218,0,0,255,255,255,101,0,0,4,135,6,114,16,38,2,247,0,0,16,7,7,15,253,118,0,0,255,255,253,138,0,0,4,135,6,114,16,38,2,247,0,0,16,7,6,228,252,149,0,0,255,255,253,138,0,0,4,135,6,114, +16,38,2,247,0,0,16,7,6,241,252,149,0,0,255,255,254,182,0,0,4,135,6,114,16,38,2,247,0,0,16,7,6,229,253,143,0,0,255,255,254,162,0,0,4,135,6,114,16,38,2,247,0,0,16,7,6,242,253,143,0,0,255,255,254,249,0,0,4,135,7,209,16,38,2,247,0,0,16,7,6,230,253,218,0, +0,255,255,254,174,0,0,4,135,7,209,16,38,2,247,0,0,16,7,6,243,253,143,0,0,255,255,0,70,255,231,4,149,6,102,16,38,2,255,0,0,16,6,0,67,0,0,0,0,255,255,0,70,255,231,4,149,6,102,16,6,2,250,0,0,255,255,0,169,255,234,4,40,6,102,16,38,3,3,0,0,16,6,0,67,0,0,0, +0,255,255,0,169,255,234,4,40,6,102,16,6,2,251,0,0,255,255,0,195,254,86,4,27,6,102,16,38,3,5,0,0,16,6,0,67,0,0,0,0,255,255,0,195,254,86,4,27,6,102,16,6,2,252,0,0,255,255,1,23,0,0,3,207,6,102,16,38,3,7,0,0,16,6,0,67,0,0,0,0,255,255,1,54,0,0,3,207,6,102, +16,6,2,253,0,0,255,255,0,137,255,227,4,72,6,102,16,38,3,13,0,0,16,6,0,67,0,0,0,0,255,255,0,137,255,227,4,72,6,102,16,6,3,26,0,0,255,255,0,51,0,0,4,105,6,102,16,38,3,19,0,0,16,6,0,67,0,0,0,0,255,255,0,51,0,0,4,105,6,102,16,6,3,27,0,0,255,255,0,70,255, +227,4,140,6,102,16,38,3,23,0,0,16,6,0,67,0,0,0,0,255,255,0,70,255,227,4,140,6,102,16,6,3,28,0,0,255,255,0,70,254,86,4,149,6,114,16,38,6,39,0,0,16,6,2,207,156,0,0,0,255,255,0,70,254,86,4,149,6,114,16,38,6,40,0,0,16,6,2,207,156,0,0,0,255,255,0,70,254,86, +4,149,6,114,16,38,6,41,0,0,16,6,2,207,156,0,0,0,255,255,0,70,254,86,4,149,6,114,16,38,6,42,0,0,16,6,2,207,156,0,0,0,255,255,0,70,254,86,4,149,6,114,16,38,2,207,156,0,16,6,6,43,0,0,0,0,255,255,0,70,254,86,4,149,6,114,16,38,2,207,156,0,16,6,6,44,0,0,0, +0,255,255,0,70,254,86,4,149,7,209,16,38,6,45,0,0,16,6,2,207,156,0,0,0,255,255,0,70,254,86,4,149,7,209,16,38,6,46,0,0,16,6,2,207,156,0,0,0,255,255,0,37,254,86,4,172,6,114,16,38,6,47,0,0,16,6,6,214,0,0,0,0,255,255,0,37,254,86,4,172,6,114,16,38,6,48,0,0, +16,6,6,214,0,0,0,0,255,255,254,107,254,86,4,172,6,114,16,38,6,49,0,0,16,6,6,214,0,0,0,0,255,255,254,107,254,86,4,172,6,114,16,38,6,50,0,0,16,6,6,214,0,0,0,0,255,255,255,26,254,86,4,172,6,114,16,38,6,214,0,0,16,6,6,51,0,0,0,0,255,255,255,6,254,86,4,172, +6,114,16,38,6,214,0,0,16,6,6,52,0,0,0,0,255,255,255,193,254,86,4,172,7,209,16,38,6,53,0,0,16,6,6,214,0,0,0,0,255,255,255,143,254,86,4,172,7,209,16,38,6,54,0,0,16,6,6,214,0,0,0,0,255,255,0,195,254,86,4,27,6,114,16,38,6,67,0,0,16,7,2,207,254,200,0,0,255, +255,0,195,254,86,4,27,6,114,16,38,6,68,0,0,16,7,2,207,254,200,0,0,255,255,0,195,254,86,4,27,6,114,16,38,6,69,0,0,16,7,2,207,254,200,0,0,255,255,0,195,254,86,4,27,6,114,16,38,6,70,0,0,16,7,2,207,254,200,0,0,255,255,0,195,254,86,4,30,6,114,16,39,2,207, +254,200,0,0,16,6,6,71,0,0,255,255,0,195,254,86,4,30,6,114,16,39,2,207,254,200,0,0,16,6,6,72,0,0,255,255,0,195,254,86,4,27,7,209,16,38,6,73,0,0,16,7,2,207,254,200,0,0,255,255,0,195,254,86,4,27,7,209,16,38,6,74,0,0,16,7,2,207,254,200,0,0,255,255,255,76, +254,86,4,72,6,114,16,38,6,75,0,0,16,6,6,214,0,0,0,0,255,255,255,76,254,86,4,72,6,114,16,38,6,76,0,0,16,6,6,214,0,0,0,0,255,255,253,63,254,86,4,72,6,114,16,38,6,77,0,0,16,6,6,214,0,0,0,0,255,255,253,63,254,86,4,72,6,114,16,38,6,78,0,0,16,6,6,214,0,0,0, +0,255,255,253,163,254,86,4,72,6,114,16,38,6,214,0,0,16,6,6,79,0,0,0,0,255,255,253,143,254,86,4,72,6,114,16,38,6,214,0,0,16,6,6,80,0,0,0,0,255,255,254,99,254,86,4,72,7,209,16,38,6,81,0,0,16,6,6,214,0,0,0,0,255,255,254,99,254,86,4,72,7,209,16,38,6,82,0, +0,16,6,6,214,0,0,0,0,255,255,0,70,254,86,4,140,6,114,16,38,6,123,0,0,16,6,2,207,0,0,0,0,255,255,0,70,254,86,4,140,6,114,16,38,6,124,0,0,16,6,2,207,0,0,0,0,255,255,0,70,254,86,4,140,6,114,16,38,6,125,0,0,16,6,2,207,0,0,0,0,255,255,0,70,254,86,4,140,6, +114,16,38,6,126,0,0,16,6,2,207,0,0,0,0,255,255,0,70,254,86,4,140,6,114,16,38,2,207,0,0,16,6,6,127,0,0,0,0,255,255,0,70,254,86,4,140,6,114,16,38,2,207,0,0,16,6,6,128,0,0,0,0,255,255,0,70,254,86,4,140,7,209,16,38,6,129,0,0,16,6,2,207,0,0,0,0,255,255,0, +70,254,86,4,140,7,209,16,38,6,130,0,0,16,6,2,207,0,0,0,0,255,255,255,201,254,86,4,135,6,114,16,38,6,131,0,0,16,6,6,214,0,0,0,0,255,255,255,101,254,86,4,135,6,114,16,38,6,132,0,0,16,6,6,214,0,0,0,0,255,255,253,138,254,86,4,135,6,114,16,38,6,133,0,0,16, +6,6,214,0,0,0,0,255,255,253,138,254,86,4,135,6,114,16,38,6,134,0,0,16,6,6,214,0,0,0,0,255,255,254,182,254,86,4,135,6,114,16,38,6,214,0,0,16,6,6,135,0,0,0,0,255,255,254,162,254,86,4,135,6,114,16,38,6,214,0,0,16,6,6,136,0,0,0,0,255,255,254,249,254,86,4, +135,7,209,16,38,6,137,0,0,16,6,6,214,0,0,0,0,255,255,254,174,254,86,4,135,7,209,16,38,6,138,0,0,16,6,6,214,0,0,0,0,255,255,0,70,255,231,4,149,6,72,16,38,2,142,0,0,16,6,2,255,0,0,0,0,255,255,0,70,255,231,4,149,5,246,16,38,2,140,0,0,16,6,2,255,0,0,0,0, +255,255,0,70,254,86,4,149,6,102,16,38,6,139,0,0,16,6,2,207,156,0,0,0,255,255,0,70,254,86,4,149,4,121,16,38,2,255,0,0,16,6,2,207,156,0,0,0,255,255,0,70,254,86,4,149,6,102,16,38,2,250,0,0,16,6,2,207,156,0,0,0,255,255,0,70,255,231,4,149,6,55,16,38,2,255, +0,0,16,6,6,216,0,0,0,0,255,255,0,70,254,86,4,149,6,55,16,38,6,206,0,0,16,6,2,207,156,0,0,0,255,255,0,37,0,0,4,172,7,109,16,38,13,6,0,0,16,6,2,224,0,0,0,0,255,255,0,37,0,0,4,172,7,48,16,38,13,11,0,0,16,6,2,224,0,0,0,0,255,255,255,135,0,0,4,172,6,102,16, +38,2,224,0,0,16,7,7,3,254,112,0,0,255,255,0,25,0,0,4,172,6,102,16,6,2,215,0,0,255,255,0,37,254,86,4,172,5,213,16,38,2,224,0,0,16,6,6,214,0,0,0,0,255,255,1,239,4,194,2,225,6,114,16,6,6,215,0,0,255,255,2,30,254,86,2,250,255,164,16,6,2,207,0,0,0,1,1,239, +4,194,2,225,6,114,0,8,0,0,1,16,35,53,50,53,35,53,51,2,225,241,142,142,241,5,195,254,255,100,157,175,255,255,1,31,5,29,3,178,6,55,16,6,2,121,0,0,255,255,1,31,5,70,3,178,7,139,16,38,0,106,0,0,16,7,6,216,0,0,1,84,255,255,0,195,254,86,4,27,6,102,16,38,6, +143,0,0,16,7,2,207,254,200,0,0,255,255,0,195,254,86,4,27,4,123,16,38,3,5,0,0,16,7,2,207,254,200,0,0,255,255,0,195,254,86,4,27,6,102,16,38,2,252,0,0,16,7,2,207,254,200,0,0,255,255,0,195,254,86,4,27,6,55,16,38,3,5,0,0,16,6,6,216,0,0,0,0,255,255,0,195,254, +86,4,27,6,55,16,38,6,221,0,0,16,7,2,207,254,200,0,0,255,255,254,141,0,0,4,78,6,102,16,38,2,228,0,0,16,7,7,3,253,118,0,0,255,255,255,31,0,0,4,78,6,102,16,6,2,217,0,0,255,255,254,91,0,0,4,72,6,102,16,38,2,230,0,0,16,7,7,3,253,68,0,0,255,255,254,237,0,0, +4,72,6,102,16,6,2,218,0,0,255,255,0,137,254,86,4,72,5,213,16,38,2,230,0,0,16,6,6,214,0,0,0,0,255,255,0,245,4,194,3,240,6,114,16,39,6,215,255,6,0,0,16,7,7,3,0,250,0,0,0,0,255,255,1,39,4,194,4,30,6,114,16,39,6,215,255,56,0,0,16,6,7,14,100,0,255,255,1,31, +4,194,3,178,7,209,16,38,6,215,0,0,16,7,6,216,0,0,1,154,255,255,1,47,0,0,3,207,6,72,16,38,2,142,0,0,16,6,3,7,0,0,0,0,255,255,1,54,0,0,3,207,5,246,16,38,2,140,0,0,16,6,3,7,0,0,0,0,255,255,1,23,0,0,3,207,7,216,16,38,3,7,0,0,16,6,7,1,0,0,0,0,255,255,1,54, +0,0,3,207,7,216,16,6,2,223,0,0,255,255,1,31,0,0,3,207,6,55,16,38,3,7,0,0,16,6,6,216,0,0,0,0,255,255,1,31,0,0,3,207,7,139,16,38,3,7,0,0,16,6,6,217,0,0,0,0,255,255,0,201,0,0,4,6,7,109,16,38,13,6,0,0,16,6,2,232,0,0,0,0,255,255,0,201,0,0,4,6,7,48,16,38,13, +11,0,0,16,6,2,232,0,0,0,0,255,255,254,191,0,0,4,6,6,102,16,38,2,232,0,0,16,7,7,3,253,168,0,0,255,255,255,31,0,0,4,6,6,102,16,6,2,219,0,0,255,255,0,245,4,194,3,240,6,114,16,39,7,15,255,6,0,0,16,7,7,3,0,250,0,0,0,0,255,255,1,19,4,194,4,30,6,114,16,39,7, +15,255,36,0,0,16,6,7,14,100,0,255,255,1,31,4,194,3,178,7,209,16,38,7,15,0,0,16,7,6,216,0,0,1,154,255,255,0,51,0,0,4,105,6,72,16,38,2,142,0,0,16,6,3,19,0,0,0,0,255,255,0,51,0,0,4,105,5,246,16,38,2,140,0,0,16,6,3,19,0,0,0,0,255,255,0,51,0,0,4,105,7,216, +16,38,3,19,0,0,16,6,7,1,0,0,0,0,255,255,0,51,0,0,4,105,7,216,16,6,2,254,0,0,255,255,0,190,254,86,4,84,6,114,16,38,3,15,0,0,16,6,6,215,0,0,0,0,255,255,0,190,254,86,4,84,6,114,16,38,3,15,0,0,16,6,7,15,0,0,0,0,255,255,0,51,0,0,4,105,6,55,16,38,3,19,0,0, +16,6,6,216,0,0,0,0,255,255,0,51,0,0,4,105,7,139,16,38,3,19,0,0,16,6,6,217,0,0,0,0,255,255,0,37,0,0,4,172,7,109,16,38,13,6,0,0,16,6,2,243,0,0,0,0,255,255,0,37,0,0,4,172,7,48,16,38,13,11,0,0,16,6,2,243,0,0,0,0,255,255,254,91,0,0,4,172,6,102,16,38,2,243, +0,0,16,7,7,3,253,68,0,0,255,255,254,112,0,0,4,172,6,102,16,6,2,221,0,0,255,255,255,126,0,0,4,117,6,114,16,38,2,240,0,0,16,7,7,15,253,143,0,0,255,255,1,23,5,70,3,145,7,216,16,38,0,106,0,0,16,7,7,3,0,0,1,114,255,255,1,63,5,70,3,186,7,216,16,6,2,214,0,0, +255,255,1,23,4,238,2,246,6,102,16,6,0,67,0,0,255,255,0,70,254,86,4,140,6,102,16,38,6,151,0,0,16,6,2,207,0,0,0,0,255,255,0,70,254,86,4,140,4,96,16,38,3,23,0,0,16,6,2,207,0,0,0,0,255,255,0,70,254,86,4,140,6,102,16,38,3,28,0,0,16,6,2,207,0,0,0,0,255,255, +0,70,255,227,4,140,6,55,16,38,3,23,0,0,16,6,6,216,0,0,0,0,255,255,0,70,254,86,4,140,6,55,16,38,7,7,0,0,16,6,2,207,0,0,0,0,255,255,254,166,255,227,4,92,6,102,16,38,2,238,0,0,16,7,7,3,253,143,0,0,255,255,255,181,255,227,4,92,6,102,16,6,2,220,0,0,255,255, +254,166,0,0,4,135,6,102,16,38,2,247,0,0,16,7,7,3,253,143,0,0,255,255,255,206,0,0,4,135,6,102,16,6,2,222,0,0,255,255,0,74,254,86,4,135,5,180,16,38,2,247,0,0,16,6,6,214,0,0,0,0,255,255,1,219,4,238,3,186,6,102,16,6,0,118,0,0,0,1,1,239,4,194,2,225,6,114, +0,8,0,0,1,53,51,21,35,6,51,21,34,1,240,240,141,1,143,241,5,195,175,175,157,100,0,1,1,100,1,223,3,109,2,131,0,3,0,17,182,0,160,2,4,1,0,4,16,212,196,49,0,16,212,236,48,1,33,21,33,1,100,2,9,253,247,2,131,164,255,255,1,100,1,223,3,109,2,131,16,6,7,27,0,0, +0,1,0,0,1,236,4,209,2,121,0,3,0,16,182,2,182,0,253,4,1,0,47,198,49,0,16,252,236,48,17,33,21,33,4,209,251,47,2,121,141,0,0,0,0,1,0,0,1,236,4,209,2,121,0,3,0,16,182,2,182,0,253,4,1,0,47,198,49,0,16,252,236,48,17,33,21,33,4,209,251,47,2,121,141,0,0,0,0, +1,0,0,1,236,4,209,2,121,0,3,0,15,181,2,182,0,4,1,0,47,196,49,0,16,212,236,48,17,33,21,33,4,209,251,47,2,121,141,0,1,0,0,1,236,4,209,2,121,0,3,0,15,181,2,182,0,4,1,0,47,196,49,0,16,212,236,48,17,33,21,33,4,209,251,47,2,121,141,255,255,1,29,254,29,3,179, +6,29,16,39,0,95,0,245,0,0,16,7,0,95,255,11,0,0,0,0,255,255,0,0,254,29,4,209,255,93,16,38,0,66,0,0,16,7,0,66,0,0,0,240,0,1,1,207,3,199,3,45,6,20,0,5,0,24,64,11,0,163,3,181,6,3,4,0,29,1,6,16,212,252,212,204,49,0,16,252,236,48,1,35,53,19,51,3,2,203,252, +196,154,98,3,199,207,1,126,254,130,0,0,0,0,1,1,207,3,199,3,45,6,20,0,5,0,24,64,11,3,163,0,181,6,3,4,1,29,0,6,16,212,236,212,204,49,0,16,252,236,48,1,51,21,3,35,19,2,49,252,197,153,98,6,20,206,254,129,1,127,0,0,0,0,1,1,147,254,225,2,242,1,47,0,5,0,26, +178,3,163,0,184,1,1,182,6,3,4,1,29,0,6,16,212,236,212,204,49,0,16,252,236,48,1,51,21,3,35,19,1,246,252,197,154,99,1,47,207,254,129,1,127,0,0,1,1,207,3,199,3,45,6,20,0,5,0,0,1,21,19,35,3,53,2,203,98,153,197,6,20,206,254,129,1,127,206,0,0,0,0,2,0,211,3, +199,3,254,6,20,0,5,0,11,0,37,64,18,6,0,163,9,3,181,12,3,4,0,29,1,7,29,6,9,10,12,16,212,204,212,236,212,252,212,204,49,0,16,252,60,236,50,48,1,35,53,19,51,3,5,35,53,19,51,3,3,156,252,196,154,98,254,53,254,199,153,98,3,199,207,1,126,254,130,207,207,1,126, +254,130,0,0,0,2,0,211,3,199,3,252,6,20,0,5,0,11,0,39,64,19,9,3,163,6,0,181,12,9,10,6,3,4,1,29,0,6,29,7,12,16,212,236,212,236,212,204,16,212,206,49,0,16,252,60,236,50,48,1,51,21,3,35,19,37,51,21,3,35,19,3,0,252,197,153,98,254,53,252,196,154,98,6,20,206, +254,129,1,127,206,206,254,129,1,127,0,2,0,211,254,225,3,252,1,47,0,5,0,11,0,42,180,9,3,163,6,0,184,1,1,64,13,12,9,10,6,3,4,1,29,0,6,29,7,12,16,212,236,212,236,212,204,16,212,206,49,0,16,252,60,236,50,48,1,51,21,3,35,19,37,51,21,3,35,19,3,0,252,197,153, +98,254,53,252,196,154,98,1,47,207,254,129,1,127,207,207,254,129,1,127,0,0,2,0,211,3,199,3,252,6,20,0,5,0,11,0,0,1,21,19,35,3,53,33,21,19,35,3,53,1,207,98,153,197,2,199,98,154,196,6,20,206,254,129,1,127,206,206,254,129,1,127,206,0,1,0,162,255,59,4,47, +5,213,0,11,0,39,64,20,8,4,203,10,2,0,136,6,202,12,3,82,5,1,81,9,82,7,0,12,16,212,60,236,252,60,236,49,0,16,228,244,212,60,236,50,48,1,51,17,33,21,33,17,35,17,33,53,33,2,16,177,1,110,254,146,177,254,146,1,110,5,213,254,92,153,251,163,4,93,153,0,0,1,0, +162,255,59,4,47,5,213,0,19,0,60,64,31,18,6,203,0,16,8,203,14,10,12,4,0,2,202,12,136,20,15,0,82,17,13,1,81,9,5,82,11,7,3,20,16,212,60,60,236,50,252,60,60,236,50,49,0,16,228,244,196,50,16,212,60,238,50,16,238,50,48,37,33,17,35,17,33,53,33,17,33,53,33,17, +51,17,33,21,33,17,33,4,47,254,146,177,254,146,1,110,254,146,1,110,177,1,110,254,146,1,110,223,254,92,1,164,154,2,31,153,1,164,254,92,153,253,225,0,0,0,1,1,63,1,209,3,145,4,33,0,11,0,18,183,9,208,3,12,6,86,0,12,16,212,236,49,0,16,212,228,48,1,52,54,51, +50,22,21,20,6,35,34,38,1,63,172,125,124,173,174,125,124,171,2,250,124,171,172,123,124,173,171,0,0,1,1,63,1,129,3,225,4,113,0,2,0,0,1,17,1,1,63,2,162,1,129,2,240,254,136,0,0,3,0,80,0,0,4,127,1,49,0,3,0,7,0,11,0,35,64,17,8,4,0,162,10,6,2,4,29,5,8,29,9, +1,29,0,12,16,212,252,212,236,212,236,49,0,47,60,60,236,50,50,48,19,51,17,35,1,51,17,35,1,51,17,35,80,252,252,3,51,252,252,254,102,252,252,1,49,254,207,1,49,254,207,1,49,254,207,0,7,0,0,0,0,4,209,5,152,0,3,0,15,0,27,0,39,0,51,0,63,0,75,0,116,64,14,3,2, +37,31,1,49,0,61,13,200,19,31,200,49,184,1,2,181,37,200,43,145,67,19,184,1,2,64,38,55,7,200,73,25,3,70,2,58,52,1,40,0,28,16,58,80,70,122,52,80,64,10,80,22,122,4,80,16,34,80,46,122,16,28,80,64,40,47,196,236,196,244,236,16,238,246,238,16,238,246,238,17, +18,57,18,57,17,18,57,17,57,49,0,47,60,238,50,238,50,246,238,254,238,16,238,50,57,18,57,17,18,57,57,48,19,39,1,23,1,20,22,51,50,54,53,52,38,35,34,6,7,52,54,51,50,22,21,20,6,35,34,38,19,20,22,51,50,54,53,52,38,35,34,6,7,52,54,51,50,22,21,20,6,35,34,38, +1,20,22,51,50,54,53,52,38,35,34,6,7,52,54,51,50,22,21,20,6,35,34,38,72,37,4,20,39,252,72,95,69,68,98,99,67,69,95,121,165,120,120,166,167,119,121,164,76,97,69,69,97,99,67,69,97,121,166,121,120,166,166,120,121,166,3,12,97,69,70,96,98,68,69,97,121,166,121, +120,167,167,120,121,166,2,55,97,1,159,96,253,74,71,97,99,69,67,99,97,69,121,165,166,120,121,168,166,3,211,69,97,97,69,67,99,97,69,120,167,167,120,121,168,167,253,34,71,97,97,71,67,99,97,69,120,166,166,120,121,168,167,0,7,0,0,0,0,4,209,5,152,0,11,0,21, +0,25,0,68,0,80,0,92,0,104,0,0,17,52,54,51,50,22,21,20,6,35,34,38,54,20,22,50,54,53,52,38,35,34,3,39,1,23,1,52,54,50,23,22,23,54,55,54,51,50,23,22,23,54,55,54,51,50,22,21,20,6,35,34,39,38,39,6,7,6,35,34,39,38,39,6,7,6,35,34,38,55,20,22,51,50,54,53,52, +38,35,34,6,5,20,22,51,50,54,53,52,38,35,34,6,5,20,22,51,50,54,53,52,38,35,34,6,166,121,120,166,166,120,121,166,121,97,138,97,99,67,69,146,37,4,20,39,251,162,138,200,69,10,9,9,10,70,101,100,69,11,8,9,10,70,101,100,139,139,100,101,70,10,9,8,11,69,100,101, +70,10,9,9,10,70,99,101,137,101,79,58,56,82,82,56,58,79,1,120,81,58,58,80,82,56,58,81,1,122,81,58,58,80,82,56,58,81,4,121,120,167,167,120,121,168,167,191,138,97,97,69,67,99,253,24,97,1,159,96,253,74,121,165,83,12,14,14,12,83,83,12,13,13,12,83,166,120, +121,168,84,12,13,13,12,84,84,12,14,13,13,84,166,123,71,97,99,69,67,99,97,69,71,97,97,71,67,99,97,69,71,97,97,71,67,99,97,0,1,1,172,4,96,3,36,5,213,0,3,0,0,1,19,51,1,1,172,174,202,254,224,4,96,1,117,254,139,0,0,255,255,1,22,4,96,3,186,5,213,16,39,7,51, +0,150,0,0,16,7,7,51,255,106,0,0,0,0,255,255,0,128,4,96,4,80,5,213,16,39,7,51,1,44,0,0,16,39,7,51,254,212,0,0,16,6,7,51,0,0,0,1,1,172,4,96,3,36,5,213,0,3,0,0,1,35,1,51,3,36,86,254,222,204,4,96,1,117,255,255,1,22,4,96,3,186,5,213,16,39,7,54,0,150,0,0,16, +7,7,54,255,106,0,0,0,0,255,255,0,128,4,96,4,80,5,213,16,38,7,54,0,0,16,39,7,54,1,44,0,0,16,7,7,54,254,212,0,0,0,1,1,90,0,141,3,47,4,35,0,6,0,26,64,12,2,4,252,0,172,7,2,3,0,118,5,7,16,212,236,50,57,49,0,16,244,236,57,48,1,21,9,1,21,1,53,3,47,254,211,1, +45,254,43,4,35,191,254,244,254,244,191,1,162,82,0,0,0,1,1,164,0,141,3,121,4,35,0,6,0,26,64,12,5,3,252,0,172,7,5,1,118,3,0,7,16,212,60,236,57,49,0,16,244,236,57,48,9,1,21,1,53,9,1,1,164,1,213,254,43,1,45,254,211,4,35,254,94,82,254,94,191,1,12,1,12,0,0, +0,255,255,0,208,0,0,4,3,5,213,16,39,0,4,254,204,0,0,16,7,0,4,1,52,0,0,0,0,0,3,0,244,0,0,4,16,5,240,0,23,0,27,0,37,0,0,1,35,17,6,7,6,7,53,54,55,54,51,50,23,22,21,20,7,6,15,1,14,1,21,3,53,51,21,3,17,55,54,55,54,53,52,39,38,2,172,190,31,32,89,98,94,96,95, +104,186,111,110,34,33,94,88,69,38,197,203,6,45,62,23,24,66,37,1,145,3,173,8,12,35,68,188,57,28,28,96,96,161,76,65,66,92,86,66,84,61,253,197,254,254,5,66,254,82,45,59,44,44,49,89,55,31,255,255,0,0,5,187,4,209,6,11,16,7,0,66,0,0,7,158,0,0,0,1,255,188,254, +27,5,20,255,133,0,12,0,0,0,32,36,55,21,6,4,35,34,36,39,53,22,1,186,1,90,1,84,172,176,254,171,168,167,254,173,177,172,254,181,104,104,126,118,118,117,119,126,105,0,0,0,1,1,207,254,242,3,119,6,20,0,11,0,0,1,33,21,35,17,51,21,35,17,51,21,33,1,207,1,168, +240,240,240,240,254,88,6,20,143,253,69,143,253,70,143,0,0,0,0,1,1,90,254,242,3,2,6,20,0,11,0,0,1,17,33,53,51,17,35,53,51,17,35,53,3,2,254,88,240,240,240,240,6,20,248,222,143,2,186,143,2,187,143,0,0,0,255,255,0,33,0,0,4,177,5,240,16,39,13,10,254,188,0, +0,16,7,13,10,1,28,0,0,0,0,255,255,0,33,0,0,4,3,5,240,16,39,13,10,254,188,0,0,16,7,0,4,1,52,0,0,0,0,255,255,0,208,0,0,4,177,5,240,16,39,0,4,254,204,0,0,16,7,13,10,1,28,0,0,0,0,0,1,0,203,255,59,4,103,5,213,0,13,0,0,1,50,4,21,20,6,7,17,35,17,35,17,35,17, +2,139,215,1,5,236,215,141,191,141,5,213,232,190,184,221,17,252,178,6,31,249,225,6,154,0,0,0,0,3,1,61,2,141,3,149,5,240,0,12,0,28,0,44,0,0,0,52,55,54,51,50,23,22,21,20,7,6,34,19,34,7,6,21,20,23,22,51,50,55,54,53,52,39,38,39,50,23,22,21,20,7,6,35,34,39, +38,53,52,55,54,2,22,24,23,34,37,23,24,24,25,70,36,87,43,44,44,43,87,88,43,44,44,43,88,149,76,76,76,76,149,150,74,75,75,76,4,32,64,23,22,22,23,32,33,20,21,1,161,85,85,175,174,85,85,85,85,174,175,85,85,89,110,109,215,214,110,109,109,110,214,215,109,110, +0,2,1,72,2,156,3,136,6,3,0,9,0,13,0,0,1,33,17,51,21,33,53,51,17,35,19,51,21,35,1,122,1,40,230,253,192,230,180,180,116,116,5,15,253,221,80,80,1,211,1,68,130,0,0,0,0,2,1,12,2,156,3,141,5,223,0,10,0,13,0,53,179,11,0,12,2,184,1,9,178,8,4,6,186,1,10,0,0,1, +21,64,11,14,12,9,11,7,87,3,5,1,9,14,16,212,212,60,196,236,50,17,57,49,0,16,244,244,212,60,236,50,17,57,48,1,51,17,51,21,35,21,35,53,33,53,9,1,33,2,119,162,116,116,138,254,125,1,131,254,238,1,18,5,223,253,230,111,186,186,121,1,147,254,99,0,0,0,0,1,1,63, +2,141,3,125,5,223,0,33,0,0,1,33,21,33,21,62,1,51,50,23,22,21,20,7,6,35,34,38,39,53,22,23,22,51,50,54,53,52,38,35,34,7,6,7,1,102,1,214,254,157,26,54,28,144,84,84,88,89,153,74,122,48,52,63,57,60,104,112,116,103,51,47,48,44,5,223,95,204,9,8,77,76,131,132, +76,76,18,18,114,26,15,14,98,91,89,100,10,11,20,0,0,2,1,73,2,141,3,161,5,240,0,29,0,41,0,0,1,21,46,1,35,34,7,6,21,54,55,54,51,50,23,22,21,20,7,6,35,34,38,53,52,54,51,50,23,22,3,34,6,20,22,51,50,55,54,52,39,38,3,93,39,88,48,119,62,61,32,50,53,68,135,73, +74,76,76,137,161,150,180,171,46,46,46,180,80,92,92,80,83,42,42,42,42,5,207,104,20,22,81,81,158,59,28,30,74,74,137,135,75,74,208,225,212,222,9,8,254,142,104,184,104,50,49,194,49,50,0,0,0,1,1,61,2,156,3,133,5,223,0,6,0,0,1,33,21,1,35,1,33,1,61,2,72,254, +180,131,1,67,254,68,5,223,48,252,237,2,228,0,0,3,1,59,2,140,3,150,5,238,0,14,0,46,0,61,0,0,1,34,7,6,20,23,22,51,50,55,54,53,52,39,38,39,38,39,38,53,52,55,54,51,50,23,22,21,20,7,6,7,22,23,22,21,20,7,6,35,34,39,38,53,52,55,54,55,20,23,22,51,50,55,54,53, +52,38,35,34,7,6,2,104,84,45,46,46,47,82,85,45,46,46,47,192,80,45,45,75,75,129,130,75,75,45,45,80,93,49,50,80,80,142,141,80,80,50,49,48,39,40,75,76,40,39,78,77,75,40,39,4,41,43,42,154,43,43,42,43,78,77,42,43,47,18,50,51,71,99,59,58,58,59,99,71,51,50,18, +19,56,56,89,113,63,64,63,64,112,90,56,56,198,67,35,36,36,35,67,68,72,36,36,0,0,0,0,2,1,48,2,141,3,136,5,240,0,15,0,46,0,0,1,50,55,54,53,52,39,38,35,34,7,6,21,20,23,22,3,53,30,1,51,50,55,54,53,14,1,35,34,39,38,53,52,55,54,51,50,23,22,21,20,7,6,35,34,39, +38,2,83,80,45,46,46,45,80,83,43,42,42,42,140,40,88,47,120,61,61,29,106,68,136,72,73,75,76,137,162,75,75,90,91,172,45,46,46,4,15,52,52,93,92,52,52,50,49,97,98,50,49,254,159,104,20,22,81,80,158,56,60,74,75,137,135,74,74,104,105,225,211,111,111,8,9,0,0, +1,1,28,2,219,3,182,5,44,0,11,0,0,1,21,33,21,33,21,35,53,33,53,33,53,2,158,1,24,254,232,106,254,232,1,24,5,44,249,95,249,249,95,249,0,0,0,0,1,1,28,3,212,3,182,4,51,0,3,0,0,1,33,21,33,1,28,2,154,253,102,4,51,95,0,0,2,1,28,3,97,3,182,4,165,0,3,0,7,0,0,1, +33,21,33,17,33,21,33,1,28,2,154,253,102,2,154,253,102,3,193,96,1,68,95,0,1,1,216,2,5,2,250,6,2,0,12,0,0,1,14,1,21,20,22,23,35,46,1,52,54,55,2,250,84,84,84,84,102,94,94,94,94,6,2,127,254,129,128,254,129,133,253,250,253,132,0,0,1,1,216,2,5,2,249,6,2,0, +13,0,0,1,51,30,1,21,20,6,7,35,62,1,53,52,38,1,216,101,95,93,93,95,101,84,83,83,6,2,132,253,125,126,253,132,130,254,127,128,254,0,1,1,65,2,156,3,144,5,31,0,19,0,32,64,6,0,3,14,10,11,20,16,212,220,60,47,204,75,49,0,64,6,6,17,12,2,11,20,16,212,60,196,212, +204,48,1,17,35,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,22,3,144,116,78,78,94,108,117,117,41,113,74,121,125,4,23,254,133,1,119,89,89,107,92,254,158,2,115,97,56,56,134,0,0,255,255,1,61,255,241,3,149,3,84,18,7,7,70,0,0,253,100,0,0,255,255,1,88,0,0, +3,147,3,67,18,7,0,123,0,0,253,100,0,0,255,255,1,66,0,0,3,125,3,84,18,7,0,116,0,0,253,100,0,0,255,255,1,70,255,241,3,156,3,84,18,7,0,117,0,0,253,100,0,0,255,255,1,12,0,0,3,141,3,67,18,7,7,72,0,0,253,100,0,0,255,255,1,63,255,241,3,125,3,67,18,7,7,73,0, +0,253,100,0,0,255,255,1,73,255,241,3,161,3,84,18,7,7,74,0,0,253,100,0,0,255,255,1,61,0,0,3,133,3,67,18,7,7,75,0,0,253,100,0,0,255,255,1,59,255,240,3,150,3,82,18,7,7,76,0,0,253,100,0,0,255,255,1,48,255,241,3,136,3,84,18,7,7,77,0,0,253,100,0,0,255,255, +1,28,0,63,3,182,2,144,18,7,7,78,0,0,253,100,0,0,255,255,1,28,1,56,3,182,1,151,18,7,7,79,0,0,253,100,0,0,255,255,1,28,0,197,3,182,2,9,18,7,7,80,0,0,253,100,0,0,255,255,1,216,255,105,2,250,3,102,18,7,7,81,0,0,253,100,0,0,255,255,1,216,255,105,2,249,3,102, +18,7,7,82,0,0,253,100,0,0,255,255,1,69,255,240,3,140,2,130,18,7,5,44,0,0,253,100,0,0,255,255,1,49,255,240,3,160,2,130,18,7,5,50,0,0,253,100,0,0,255,255,1,58,255,240,3,151,2,130,18,7,5,59,0,0,253,100,0,0,255,255,1,18,0,0,3,191,2,115,18,7,2,127,0,0,253, +100,0,0,255,255,1,49,255,240,3,160,2,130,18,7,5,51,0,0,253,100,0,0,255,255,1,65,0,0,3,144,3,104,18,7,2,86,0,0,253,100,0,0,255,255,1,56,0,0,3,153,3,103,18,7,5,56,0,0,253,100,0,0,255,255,1,86,0,0,3,124,3,110,18,7,2,125,0,0,253,100,0,0,255,255,1,37,0,0, +3,172,2,130,18,7,5,57,0,0,253,100,0,0,255,255,1,65,0,0,3,144,2,131,18,7,7,83,0,0,253,100,0,0,255,255,1,71,255,17,3,138,2,130,18,7,5,63,0,0,253,100,0,0,255,255,1,91,0,0,3,118,2,147,18,7,2,126,0,0,253,100,0,0,255,255,1,77,0,0,3,132,3,37,18,7,5,64,0,0,253, +100,0,0,0,1,0,10,255,233,4,204,5,229,0,35,0,0,1,14,1,35,34,2,16,18,51,50,22,23,21,46,1,35,34,6,16,22,51,50,54,55,17,33,21,33,17,33,21,33,17,33,21,33,2,175,59,134,74,190,220,220,190,76,133,58,57,130,73,144,153,153,144,73,130,57,2,19,254,94,1,145,254,111, +1,172,253,227,1,172,55,56,1,63,2,42,1,63,55,55,163,73,71,239,254,56,239,71,73,2,23,131,254,173,131,254,96,131,0,0,0,3,0,123,255,166,4,99,6,57,0,39,0,46,0,52,0,0,1,22,23,55,51,7,22,23,21,38,39,1,51,50,54,55,21,14,1,35,34,39,7,35,55,38,39,7,35,55,38,39, +38,17,16,55,54,63,1,51,7,6,7,6,17,20,23,1,38,39,1,22,23,3,44,59,56,28,141,43,36,34,53,58,254,222,16,108,192,85,88,197,110,24,24,16,141,22,59,52,34,141,59,18,15,162,162,146,240,19,142,207,132,80,113,74,2,1,56,61,254,222,48,59,5,235,8,19,105,165,22,28, +213,60,41,251,151,94,95,211,72,72,2,63,87,18,30,135,230,18,21,207,1,103,1,106,206,185,20,75,252,31,112,157,254,216,238,148,3,203,19,4,251,149,40,21,0,0,0,1,0,95,255,228,4,89,5,240,0,44,0,0,37,54,55,54,55,21,14,1,35,32,0,17,16,0,33,50,22,23,21,46,1,35, +34,2,17,16,23,22,23,17,51,21,62,1,51,50,22,31,1,46,1,35,34,6,21,2,243,89,81,98,85,89,200,111,254,227,254,184,1,72,1,29,113,200,87,85,195,110,215,229,114,86,141,140,44,142,101,14,35,21,1,24,55,33,118,128,138,7,39,47,95,211,72,71,1,158,1,103,1,104,1,159, +71,71,213,95,94,254,199,254,216,254,217,156,117,30,3,93,157,92,89,4,5,170,16,15,182,171,0,0,0,1,0,0,0,0,4,67,5,213,0,17,0,0,19,17,33,21,33,17,33,21,33,17,51,21,35,17,35,17,35,53,233,3,90,253,112,2,80,253,176,247,247,202,233,1,126,4,87,170,254,72,170, +254,181,69,254,199,1,57,69,0,0,0,0,1,0,139,0,0,4,108,5,240,0,35,0,0,1,17,33,21,33,53,51,17,35,53,51,53,35,53,51,53,16,54,51,50,22,23,21,46,1,35,34,6,29,1,33,21,33,21,33,21,2,63,2,45,252,31,236,191,191,199,199,214,232,61,151,79,76,136,61,148,116,1,135, +254,121,1,143,1,236,254,190,170,170,1,66,143,143,143,95,1,5,243,31,29,182,41,41,155,212,72,143,143,143,0,0,1,0,109,255,66,4,111,5,30,0,41,0,0,1,54,51,50,22,25,1,35,17,52,38,35,34,6,21,17,35,53,3,35,19,38,39,38,35,34,6,21,17,35,17,51,21,62,1,51,50,23, +22,23,19,51,3,10,48,63,135,111,168,53,70,80,59,168,93,105,198,1,28,28,74,73,57,167,167,33,99,63,76,51,33,23,66,106,4,98,25,209,254,223,253,119,2,129,237,115,123,229,253,127,176,254,146,3,69,235,55,56,123,229,253,127,4,96,96,60,63,35,23,39,1,4,0,0,0,5, +0,0,0,0,4,209,5,213,0,2,0,6,0,34,0,38,0,41,0,0,1,39,21,19,39,35,21,3,33,19,51,17,51,17,51,21,35,21,51,21,35,17,33,3,35,17,35,17,35,53,51,53,35,53,51,5,23,51,53,3,23,53,1,181,79,183,57,126,196,1,16,211,230,196,162,162,162,162,254,240,211,230,196,162,162, +162,162,2,18,57,126,79,79,3,175,206,206,254,242,147,147,3,52,253,218,2,38,253,218,123,147,123,253,218,2,38,253,218,2,38,123,147,123,123,147,147,254,242,206,206,0,2,0,10,255,227,4,204,5,213,0,8,0,80,0,0,19,17,51,50,54,53,52,38,35,19,6,7,6,43,1,17,35,17, +51,50,23,22,23,51,17,51,17,51,21,35,17,20,22,59,1,53,30,1,51,50,54,53,52,38,47,1,46,1,53,52,54,51,50,22,23,21,46,1,35,34,6,21,20,22,31,1,30,1,21,20,6,35,34,38,39,53,35,34,38,53,17,110,126,70,77,77,70,252,3,60,64,125,126,100,226,125,64,46,13,42,92,189, +189,38,57,90,50,99,48,64,70,50,85,32,85,75,111,103,50,89,38,39,83,45,68,68,49,74,31,97,82,123,107,45,96,54,90,106,81,5,47,253,207,146,135,134,146,254,204,200,106,113,253,168,5,213,113,82,136,1,62,254,194,143,253,160,137,78,35,53,53,89,81,75,80,37,15, +36,149,130,158,172,30,30,174,40,40,84,84,64,73,33,14,42,153,137,156,182,35,35,1,159,210,2,96,0,0,0,0,2,0,10,255,227,4,201,5,213,0,7,0,69,0,0,19,17,51,50,54,16,38,35,1,23,35,3,46,1,43,1,17,35,17,33,50,22,21,20,6,7,30,1,31,1,22,23,22,51,50,54,53,52,38, +47,1,46,1,53,52,54,51,50,22,23,21,46,1,35,34,6,21,20,22,31,1,30,1,21,20,6,35,34,39,38,139,163,93,96,96,93,1,194,2,139,122,47,89,77,141,129,1,36,164,161,84,80,42,78,40,58,63,62,63,62,83,90,65,109,41,110,97,143,132,65,116,48,50,107,58,87,88,63,94,41,125, +106,158,139,57,62,28,5,47,253,238,135,1,6,133,250,216,7,1,127,150,98,253,137,5,213,214,216,141,186,36,22,144,126,180,51,25,27,89,81,75,80,37,15,36,149,130,158,172,30,30,174,40,40,84,84,64,73,33,14,42,153,137,156,182,18,8,0,0,6,0,0,0,0,4,209,5,213,0,3, +0,6,0,10,0,42,0,45,0,48,0,0,19,23,51,55,1,35,27,1,33,23,51,1,33,55,51,23,33,55,51,7,51,21,35,7,51,21,35,3,35,3,35,3,35,3,35,53,51,39,35,53,51,39,51,27,3,7,51,236,14,225,18,1,217,185,112,103,254,253,18,228,253,5,1,49,30,140,30,1,32,23,197,29,29,50,17, +67,89,134,191,191,14,200,191,134,89,68,18,50,29,29,197,70,73,110,166,19,36,4,132,117,117,254,252,253,151,3,109,117,1,4,194,194,194,194,143,117,143,252,128,3,119,252,137,3,128,143,117,143,194,253,171,253,153,2,103,1,4,117,0,0,0,2,0,42,255,227,4,167,5, +213,0,13,0,27,0,0,19,37,50,18,25,1,35,17,52,38,35,33,17,35,41,1,34,2,25,1,51,17,20,22,51,33,17,51,42,1,163,206,212,149,127,142,254,242,149,4,124,254,97,206,212,149,126,143,1,17,143,5,210,3,254,214,254,220,254,145,1,86,240,211,250,178,1,42,1,36,1,111, +254,170,240,211,5,78,0,0,255,255,0,123,254,155,4,209,6,20,18,38,0,211,0,0,16,6,2,108,122,0,0,0,0,1,0,37,255,227,4,37,5,240,0,51,0,112,64,60,13,0,231,49,15,38,24,231,22,31,179,32,178,28,151,40,22,35,7,179,6,178,10,151,3,150,35,153,52,51,40,39,49,41,45, +24,22,16,3,19,15,23,14,38,0,45,25,13,23,19,14,50,39,19,30,31,6,23,45,52,16,212,196,196,50,236,196,50,196,17,18,57,57,18,57,57,17,18,57,17,23,57,18,57,57,17,57,57,49,0,16,228,244,236,244,236,16,198,50,238,246,238,16,238,50,213,60,238,50,48,19,18,0,51, +50,22,23,21,46,1,35,34,6,7,33,7,33,14,1,21,20,22,23,33,7,33,30,1,51,50,54,55,21,14,1,35,34,0,3,35,55,51,38,39,38,53,52,55,54,55,35,55,211,48,1,18,223,84,147,74,66,159,78,146,174,24,1,225,49,254,70,2,1,1,1,1,105,49,254,211,23,174,147,79,157,67,72,148, +85,226,254,237,44,174,49,117,1,1,2,2,1,1,166,49,3,180,1,27,1,33,40,42,207,61,68,208,204,108,20,45,46,15,38,23,110,203,209,67,62,207,42,40,1,32,1,28,110,12,20,45,15,18,47,19,11,108,0,1,0,42,0,0,4,167,5,213,0,17,0,0,19,17,51,17,1,51,1,33,21,33,1,35,1,17, +35,17,35,53,180,172,2,60,221,253,186,1,132,254,126,2,114,227,253,156,172,138,3,84,2,129,253,137,2,119,253,127,115,253,31,2,207,253,49,2,225,115,0,0,0,1,0,47,0,0,4,162,5,213,0,23,0,0,1,17,33,53,33,21,33,17,55,23,5,21,55,23,5,17,35,17,7,39,37,53,7,39,2, +4,254,43,4,115,254,45,229,80,254,203,230,80,254,202,203,208,77,1,29,209,77,3,141,1,158,170,170,254,241,161,111,216,136,162,111,217,253,184,1,186,161,110,217,136,162,110,0,0,0,5,0,30,254,57,4,198,5,240,0,22,0,45,0,98,0,119,0,131,0,0,1,39,19,54,55,62,1, +51,50,22,23,22,21,20,7,6,7,6,35,34,39,38,39,19,34,7,6,7,6,21,20,23,22,51,50,54,55,54,55,54,53,52,39,38,39,38,5,54,55,19,6,7,6,7,6,7,39,62,1,55,54,51,50,22,23,30,1,21,20,7,6,7,14,1,7,6,7,6,35,34,39,46,1,39,38,47,1,6,7,6,35,34,39,38,53,52,54,51,50,1,3, +6,7,23,22,23,22,51,50,54,55,54,55,54,53,52,39,38,39,38,1,38,35,34,7,6,21,20,23,22,51,50,3,102,98,85,18,33,26,79,51,39,65,20,34,25,26,43,48,46,29,33,24,16,130,46,26,6,8,6,12,17,33,19,32,12,11,10,9,15,7,12,11,252,176,7,5,95,24,17,18,13,11,9,92,14,53,35, +63,92,107,159,50,44,44,15,14,35,19,50,33,36,40,50,40,32,25,26,52,17,34,8,8,9,11,41,49,62,40,40,69,56,38,1,0,94,13,11,21,44,27,30,28,57,81,30,23,15,13,16,17,29,70,254,145,21,25,20,8,7,13,12,17,23,254,57,41,2,208,151,105,82,109,58,51,88,146,119,100,103, +55,63,32,23,50,1,248,106,26,55,35,61,53,40,54,36,32,27,54,50,57,84,47,20,12,11,183,40,50,3,77,10,20,22,33,29,58,53,83,125,36,64,123,109,98,245,129,113,140,130,126,69,115,47,52,24,29,9,10,45,19,38,10,10,34,23,84,65,66,96,93,133,3,146,252,155,124,64,27, +56,22,25,134,110,82,128,107,99,100,93,97,67,156,251,160,34,14,14,15,24,15,14,0,0,0,2,0,46,255,227,4,142,5,240,0,41,0,53,0,0,19,39,54,51,50,23,22,51,50,55,38,53,52,55,54,51,50,23,22,21,20,7,22,21,20,7,6,35,53,50,55,54,53,52,39,6,35,34,39,38,35,34,37,54, +53,52,39,38,35,34,7,6,21,20,185,139,147,111,124,64,88,34,48,55,227,80,89,136,116,97,84,107,181,126,106,252,134,91,73,119,137,109,113,74,50,53,51,2,48,68,27,35,50,52,33,25,2,4,96,240,78,107,66,177,254,172,88,96,96,83,177,227,171,163,191,194,134,113,162, +74,60,147,88,114,126,104,70,217,108,175,86,49,63,63,48,87,166,0,0,0,0,4,0,106,0,0,4,209,5,213,0,26,0,31,0,36,0,41,0,0,19,33,32,19,51,21,35,22,7,51,21,35,6,7,6,43,1,17,35,17,35,53,51,53,35,53,51,55,21,33,38,35,19,33,21,51,50,55,54,39,33,21,197,1,180,1, +130,94,120,95,9,8,94,114,38,97,126,225,234,202,91,91,91,91,202,1,220,77,165,253,254,25,234,177,117,7,9,253,242,5,213,254,247,116,58,57,115,123,70,89,253,168,3,114,115,115,116,99,99,99,254,67,116,231,59,56,115,0,0,2,0,53,255,91,4,137,6,120,0,36,0,45,0, +0,5,35,53,38,39,38,17,16,55,54,55,53,51,21,22,23,22,23,21,38,39,38,39,17,54,55,54,55,17,35,53,33,17,6,7,6,7,39,17,6,7,6,17,16,23,22,2,209,140,223,137,168,168,137,223,140,105,96,112,94,95,107,98,107,78,63,72,57,120,1,34,99,120,104,117,140,133,79,111,111, +79,165,143,31,167,204,1,109,1,110,205,166,31,143,137,4,31,36,70,215,95,48,44,4,251,63,2,17,18,39,1,145,166,253,127,83,42,37,5,178,4,167,32,108,153,254,209,254,210,153,108,0,0,3,0,39,0,0,4,169,5,213,0,23,0,27,0,30,0,0,19,53,33,19,51,19,33,21,35,23,51, +21,35,19,35,3,33,3,35,19,35,53,51,55,51,7,33,47,1,51,3,70,1,22,165,208,165,1,20,237,65,172,133,164,191,154,254,51,155,193,164,133,172,67,175,61,1,131,62,227,191,96,3,82,123,2,8,253,248,123,207,123,253,248,2,8,253,248,2,8,123,207,207,207,123,1,65,0,0, +0,0,1,0,0,255,227,4,209,5,240,0,54,0,0,1,54,55,54,53,52,38,35,34,6,7,53,62,1,51,50,4,21,20,7,51,21,35,6,15,1,33,21,33,6,21,20,22,51,50,54,55,21,14,1,35,34,36,53,52,55,35,53,51,54,55,54,55,33,53,3,63,10,9,55,166,143,94,185,92,105,190,86,223,1,13,21,156, +233,94,204,39,2,58,252,167,44,170,153,104,205,115,107,212,105,252,254,248,18,157,217,9,9,72,136,254,69,3,175,7,9,52,99,113,133,60,59,205,39,39,241,200,75,61,123,91,47,9,123,57,98,123,137,68,73,215,45,45,224,213,78,64,123,11,10,79,47,123,0,0,0,0,2,0,130, +254,211,4,79,6,20,0,33,0,44,0,0,1,21,38,39,38,35,17,50,55,54,55,21,6,7,6,7,17,35,17,38,39,38,17,53,16,55,54,55,53,55,21,22,23,22,1,3,6,7,6,7,6,23,22,23,22,4,79,91,84,85,101,101,85,84,91,89,92,89,91,100,185,115,212,212,121,178,101,93,89,92,254,138,1,91, +67,118,15,14,14,25,108,67,4,164,213,105,45,45,251,241,45,45,105,211,72,36,34,2,254,240,1,21,23,117,214,1,57,17,1,66,203,116,23,230,2,226,2,34,35,251,163,3,249,23,66,117,170,161,102,180,108,67,0,2,0,47,0,0,4,162,5,213,0,3,0,11,0,0,19,33,21,33,21,33,21, +33,17,35,17,33,47,4,115,251,141,4,115,254,45,203,254,43,5,213,170,120,170,251,247,4,9,0,0,0,0,1,0,104,0,0,4,113,5,213,0,37,0,0,1,7,33,22,23,33,7,35,6,7,6,7,22,23,22,23,19,35,3,46,1,43,1,53,51,50,55,54,55,33,55,33,38,39,38,43,1,55,4,113,55,254,167,86, +23,1,35,55,227,6,75,80,146,78,55,54,83,203,217,178,77,123,99,193,221,145,71,59,10,253,232,55,1,219,16,52,75,144,243,55,5,213,123,80,127,123,134,86,94,21,20,55,55,167,254,104,1,121,161,93,166,77,64,102,123,76,53,78,123,0,0,1,0,10,0,0,4,156,5,213,0,26, +0,0,1,16,0,33,35,17,7,39,37,53,7,39,37,17,51,17,55,23,5,21,55,23,5,17,50,18,17,4,156,254,174,254,160,172,230,78,1,52,232,76,1,52,202,230,80,254,202,232,80,254,200,211,247,2,236,254,126,254,150,2,30,161,110,216,137,162,110,217,1,228,254,170,162,111,217, +136,163,111,218,253,251,1,24,1,46,0,0,2,0,102,0,0,4,117,5,213,0,22,0,30,0,0,1,33,50,4,21,20,4,43,1,21,33,21,33,17,35,17,35,53,51,53,35,53,51,19,17,51,50,54,16,38,35,1,48,1,73,250,1,2,254,255,251,127,1,116,254,140,202,202,202,202,202,202,127,140,157,156, +141,5,213,227,219,221,226,166,166,254,244,1,12,166,166,166,2,49,253,207,148,1,10,147,0,2,0,140,255,228,4,49,5,240,0,23,0,32,0,0,37,22,51,50,54,55,21,14,1,35,32,0,17,16,0,33,50,22,23,21,46,1,34,15,1,6,7,6,17,16,23,22,23,2,1,95,124,100,157,84,9,200,132, +254,248,254,184,1,69,1,22,125,144,61,91,126,232,111,105,8,11,137,134,12,10,131,55,64,44,131,5,76,1,168,1,93,1,114,1,149,52,30,130,42,58,48,78,8,14,178,254,175,254,204,190,17,11,0,0,0,0,4,0,6,255,207,4,208,6,4,0,25,0,29,0,40,0,50,0,0,1,21,46,1,35,34,6, +21,20,22,51,50,54,55,21,14,1,35,34,38,53,52,54,51,50,22,37,51,1,35,1,34,6,21,20,22,51,50,54,16,46,1,50,22,21,20,6,34,38,53,52,1,196,58,70,35,75,86,86,75,35,70,58,45,81,46,126,148,149,131,42,80,1,202,135,253,170,135,2,195,61,73,73,61,60,74,74,181,242, +136,136,242,135,5,151,178,52,30,156,148,147,157,31,52,177,34,29,252,209,212,249,27,75,249,203,3,4,158,146,145,159,160,1,32,160,157,248,213,212,248,248,212,213,0,0,0,0,3,0,58,0,0,4,158,5,213,0,3,0,7,0,19,0,0,1,17,51,17,33,17,51,17,37,33,17,33,17,33,17, +33,17,33,17,33,3,141,189,252,68,190,254,238,1,102,1,153,1,101,254,155,254,103,254,154,5,113,250,243,5,13,250,243,5,13,100,253,136,2,120,250,43,2,219,253,37,0,0,1,0,84,0,0,4,72,6,20,0,26,0,0,1,3,35,19,54,55,54,53,52,38,35,34,6,7,3,35,1,51,3,62,1,51,50, +22,21,20,6,4,51,135,184,135,1,2,15,93,87,127,178,33,123,184,1,47,184,116,75,175,98,139,154,11,2,182,253,74,2,183,4,10,71,39,81,87,186,168,253,135,6,20,253,164,97,98,145,130,32,94,0,1,0,84,0,0,4,72,6,20,0,29,0,0,1,54,51,50,22,21,20,7,3,35,19,54,52,38, +35,34,6,7,3,35,19,7,39,63,1,51,7,37,23,5,1,199,151,197,139,154,21,135,184,135,18,93,87,127,178,33,123,184,233,222,11,254,49,184,36,1,28,14,254,193,3,184,195,145,130,69,109,253,74,2,183,72,133,87,186,168,253,135,4,173,69,98,79,251,190,89,98,99,0,0,0,2, +0,74,0,0,4,133,5,213,0,3,0,13,0,0,37,1,35,9,1,33,1,17,51,17,33,1,17,35,4,32,253,71,184,2,185,252,226,1,72,2,166,77,254,184,253,90,77,100,5,13,250,243,5,113,251,31,4,225,250,43,4,225,251,31,0,0,0,4,0,10,0,0,4,199,5,213,0,3,0,9,0,13,0,35,0,0,0,32,16,32, +19,34,16,51,50,16,3,33,21,33,1,17,51,19,17,52,54,51,21,34,6,21,17,35,3,17,20,6,35,53,50,54,3,101,1,98,254,158,177,50,50,51,228,1,98,254,158,253,32,245,204,87,220,85,38,245,204,87,220,85,38,3,12,253,234,1,149,254,236,1,20,254,9,148,1,49,4,164,251,81,3, +126,131,174,184,62,59,251,92,4,175,252,130,131,174,184,62,0,0,0,0,4,0,0,0,125,4,209,5,78,0,20,0,42,0,51,0,62,0,0,1,34,14,2,21,20,22,23,30,1,51,50,62,2,53,52,46,2,39,50,22,23,30,1,21,20,14,2,35,34,46,2,53,52,54,55,62,1,19,17,51,50,54,53,52,38,35,37,33, +50,22,21,20,6,43,1,17,35,2,104,106,181,150,77,77,75,76,181,105,106,181,152,75,76,150,181,107,127,218,90,90,92,91,182,218,126,125,218,182,91,92,90,90,218,38,147,82,88,88,82,254,248,1,8,146,149,149,146,147,117,4,231,74,150,184,106,104,183,75,76,76,76,152, +181,105,106,184,150,74,103,90,90,91,220,126,125,218,182,91,91,182,218,125,126,220,91,90,90,254,184,254,233,73,67,66,73,83,113,109,111,112,254,214,0,0,4,0,66,0,0,4,154,5,213,0,3,0,11,0,22,0,31,0,0,19,17,51,17,51,17,33,50,55,17,38,35,37,33,50,22,21,20, +6,43,1,17,33,1,17,54,55,54,53,52,39,38,162,192,96,1,32,23,22,22,23,253,96,2,115,239,246,246,240,242,254,128,3,49,58,43,89,88,42,5,113,250,243,5,13,253,106,2,2,146,2,100,219,211,213,218,253,136,5,90,253,153,22,41,86,159,158,86,41,0,0,0,0,4,0,17,254,248, +4,188,5,240,0,16,0,24,0,32,0,40,0,0,37,19,35,39,7,6,35,32,0,17,16,0,32,0,17,16,2,37,22,50,55,17,38,34,7,3,17,6,7,6,16,23,22,1,17,54,55,54,16,39,38,3,92,230,211,191,44,15,14,254,240,254,186,1,70,2,32,1,69,181,253,141,93,236,93,93,236,93,91,31,28,134,134, +28,2,123,30,27,134,134,27,27,254,221,239,3,1,1,165,1,97,1,98,1,165,254,91,254,158,254,252,254,142,11,50,50,4,215,50,50,251,106,4,84,29,37,182,253,156,181,37,4,53,251,175,29,36,182,2,99,182,36,0,5,0,37,0,0,4,189,5,213,0,9,0,30,0,38,0,46,0,50,0,0,1,38, +39,38,43,1,22,23,19,51,3,30,1,23,19,33,3,46,1,43,1,17,33,17,33,50,22,21,20,7,6,1,17,33,50,55,17,38,35,23,17,54,55,54,16,39,38,37,17,51,17,3,182,65,58,58,102,38,65,86,121,169,224,45,96,53,173,254,139,162,63,118,102,17,254,171,2,65,217,214,100,41,253,242, +1,20,21,19,19,21,129,55,37,76,75,36,253,50,172,1,127,151,48,49,47,201,254,229,2,79,25,132,126,254,104,1,127,150,98,253,137,5,213,214,216,208,98,41,2,165,253,106,2,2,146,2,23,253,153,22,41,86,1,62,85,41,45,250,243,5,13,0,0,0,0,2,0,0,3,147,4,102,5,213, +0,7,0,20,0,104,64,54,15,9,10,9,14,10,10,9,17,8,9,8,16,9,9,8,66,17,14,9,3,1,15,18,12,3,5,1,215,10,8,0,136,21,16,15,10,9,8,5,17,13,96,11,17,96,19,0,95,2,96,4,95,6,47,252,254,236,213,238,214,238,17,23,57,49,0,16,244,60,60,236,50,212,60,60,196,17,23,57,48, +75,83,88,7,16,5,201,7,16,4,201,7,16,4,201,7,16,5,201,89,34,1,21,35,17,35,17,35,53,33,27,1,51,17,35,17,3,35,3,17,35,17,1,182,162,114,162,2,180,137,125,172,114,156,55,166,113,5,213,94,254,28,1,228,94,255,0,1,0,253,190,1,226,254,211,1,45,254,30,2,66,0,2, +0,48,0,0,4,153,5,213,0,3,0,13,0,0,37,1,35,1,3,33,21,1,33,21,33,53,1,33,1,98,2,182,197,253,74,90,4,67,253,74,2,201,251,151,2,182,253,93,100,5,13,250,243,5,113,100,250,243,100,100,5,13,255,255,0,74,0,0,4,135,5,180,16,6,2,247,0,0,255,255,0,137,0,0,4,201, +5,213,16,6,0,46,0,0,255,255,0,37,0,0,4,172,7,109,16,6,0,135,0,0,0,2,0,11,255,231,4,198,5,45,0,26,0,41,0,0,55,22,23,22,32,55,54,55,51,6,7,6,32,36,2,53,52,18,36,51,50,4,18,21,33,34,21,53,20,51,33,50,53,17,38,39,38,35,34,7,6,7,233,54,75,121,1,11,123,85, +62,90,76,116,144,254,197,254,224,160,162,1,34,154,152,1,34,163,252,51,16,16,2,224,16,56,77,123,128,129,123,77,55,228,77,51,84,84,60,96,120,71,90,179,1,65,175,176,1,69,174,174,254,187,176,19,73,19,19,1,112,80,51,82,81,52,79,0,0,0,0,3,0,27,0,0,3,192,6, +20,0,9,0,13,0,17,0,0,1,33,3,33,7,33,55,33,19,35,19,51,19,35,19,51,7,35,1,66,2,33,198,1,35,19,252,110,19,1,33,179,211,132,134,179,134,79,184,45,184,4,96,252,4,100,100,3,152,252,104,3,152,2,24,233,0,0,255,255,0,27,254,242,4,90,6,123,16,38,13,4,0,0,16,39, +0,123,254,254,0,156,16,7,7,75,0,201,252,86,255,255,0,27,254,237,4,90,6,123,16,38,13,4,0,0,16,39,0,123,254,254,0,156,16,7,7,77,0,201,252,96,255,255,0,27,254,227,4,101,6,123,16,39,0,117,0,201,252,86,16,38,13,4,0,0,16,7,0,123,254,254,0,156,255,255,0,27, +254,227,4,101,6,140,16,39,0,117,0,201,252,86,16,38,13,4,0,0,16,7,0,116,254,254,0,156,255,255,0,27,254,227,4,90,6,123,16,39,7,73,0,201,252,86,16,38,13,4,0,0,16,7,0,123,254,254,0,156,255,255,0,27,254,227,4,90,6,140,16,39,7,73,0,201,252,86,16,38,13,4,0, +0,16,7,0,116,254,254,0,156,255,255,0,27,254,227,4,90,6,140,16,39,7,73,0,201,252,86,16,38,13,4,0,0,16,7,0,117,254,254,0,156,255,255,0,10,254,227,4,90,6,123,16,39,7,73,0,201,252,86,16,38,13,4,0,0,16,7,7,72,254,254,0,156,255,255,0,27,254,227,4,106,6,123, +16,39,7,74,0,201,252,86,16,38,13,4,0,0,16,7,0,123,254,254,0,156,255,255,0,27,254,227,4,106,6,123,16,39,7,74,0,201,252,86,16,38,13,4,0,0,16,7,7,73,254,254,0,156,255,255,0,27,254,226,4,95,6,123,16,39,7,76,0,201,252,86,16,38,13,4,0,0,16,7,0,123,254,254, +0,156,255,255,0,27,254,226,4,95,6,140,16,39,7,76,0,201,252,86,16,38,13,4,0,0,16,7,0,117,254,254,0,156,255,255,0,27,254,226,4,95,6,123,16,39,7,76,0,201,252,86,16,38,13,4,0,0,16,7,7,73,254,254,0,156,255,255,0,27,254,226,4,95,6,123,16,39,7,76,0,201,252, +86,16,38,13,4,0,0,16,7,7,75,254,254,0,156,255,255,0,27,1,248,4,90,6,123,16,38,13,4,0,0,16,7,0,123,254,254,0,156,255,255,0,27,254,227,4,101,6,140,16,39,7,70,254,254,0,156,16,38,13,4,0,0,16,7,0,117,0,201,252,86,0,1,0,66,0,229,4,143,3,125,0,9,0,0,19,53, +1,23,7,33,21,33,23,7,66,1,35,90,160,3,112,252,144,160,90,2,8,82,1,35,90,160,164,160,90,0,0,0,0,1,1,28,0,0,3,181,4,77,0,9,0,0,9,1,7,39,17,35,17,7,39,1,2,146,1,34,90,160,164,160,90,1,36,4,77,254,221,90,160,252,144,3,112,160,90,1,35,0,0,0,0,1,0,66,0,229, +4,143,3,125,0,9,0,0,9,1,39,55,33,53,33,39,55,1,4,143,254,221,90,160,252,144,3,112,160,90,1,35,2,8,254,221,90,160,164,160,90,254,221,0,0,0,0,1,1,28,0,0,3,181,4,77,0,9,0,0,33,1,55,23,17,51,17,55,23,1,2,64,254,220,90,160,164,160,90,254,222,1,35,90,160,3, +112,252,144,160,90,254,221,0,0,1,0,66,0,229,4,143,3,125,0,15,0,0,1,33,23,7,1,53,1,23,7,33,39,55,1,21,1,39,3,178,253,109,160,90,254,221,1,35,90,160,2,147,160,90,1,35,254,221,90,1,223,160,90,1,35,82,1,35,90,160,160,90,254,221,82,254,221,90,0,0,0,1,1,28, +0,0,3,181,4,77,0,15,0,0,37,55,23,1,35,1,55,23,17,7,39,1,51,1,7,39,2,186,160,90,254,222,82,254,220,90,160,160,90,1,36,82,1,34,90,160,221,160,90,254,221,1,35,90,160,2,147,160,90,1,35,254,221,90,160,0,0,0,0,1,0,184,0,0,4,25,3,97,0,9,0,0,19,55,33,21,35,1, +7,1,21,35,184,58,1,156,227,2,110,116,253,146,127,3,39,58,127,253,146,116,2,110,227,0,0,0,0,1,0,184,0,0,4,25,3,97,0,9,0,0,1,17,35,53,1,39,1,35,53,33,4,25,127,253,146,116,2,110,227,1,156,3,39,254,100,227,253,146,116,2,110,127,0,0,0,1,0,184,0,0,4,25,3,97, +0,9,0,0,41,1,53,51,1,55,1,53,51,17,3,223,254,100,227,253,146,116,2,110,127,127,2,110,116,253,146,227,254,100,0,1,0,184,0,0,4,25,3,97,0,9,0,0,55,17,51,21,1,23,1,51,21,33,184,127,2,110,116,253,146,227,254,100,58,1,156,227,2,110,116,253,146,127,0,1,0,66, +0,229,4,143,3,125,0,17,0,0,1,51,21,33,7,39,55,33,23,7,1,53,1,23,7,33,55,23,3,193,206,254,209,147,142,99,254,125,160,90,254,221,1,35,90,160,1,227,148,142,2,131,164,250,82,168,160,90,1,35,82,1,35,90,160,250,82,0,0,1,0,66,0,229,4,143,3,125,0,17,0,0,1,35, +53,33,55,23,7,33,39,55,1,21,1,39,55,33,7,39,1,16,206,1,47,147,142,99,1,131,160,90,1,35,254,221,90,160,254,29,148,142,1,223,164,250,82,168,160,90,254,221,82,254,221,90,160,250,82,0,0,1,0,89,1,139,4,120,3,97,0,53,0,0,1,22,23,22,23,22,51,50,55,54,55,54, +55,54,55,54,55,54,51,50,23,22,23,22,23,7,38,39,38,39,38,35,34,7,14,1,7,6,7,6,7,6,35,34,39,38,47,1,21,35,17,55,33,21,1,36,7,102,18,32,25,33,31,26,24,26,21,13,17,43,33,51,45,54,56,43,50,34,44,24,106,5,33,17,33,24,33,28,28,25,51,10,14,46,30,54,43,56,53, +46,48,36,109,127,58,1,156,2,226,12,119,21,18,15,15,12,29,22,39,48,55,41,27,23,23,28,40,54,59,67,18,43,22,19,14,14,12,58,32,44,58,39,29,24,24,25,43,128,224,1,156,58,127,0,0,1,0,89,1,139,4,120,3,97,0,53,0,0,1,33,53,33,23,17,35,53,7,6,7,6,35,34,39,38,39, +38,39,46,1,39,38,35,34,7,6,7,6,7,39,54,55,54,55,54,51,50,23,22,23,22,23,22,23,22,23,22,51,50,55,54,55,54,3,173,254,245,1,156,58,127,109,36,48,46,53,56,43,54,30,46,14,10,51,25,28,28,33,24,33,17,33,5,106,24,44,34,50,43,56,54,45,51,33,43,17,13,21,26,24, +26,31,33,25,32,18,102,2,226,127,58,254,100,224,128,43,25,24,24,29,39,58,44,32,58,12,14,14,19,22,43,18,67,59,54,40,28,23,23,27,41,55,48,39,22,29,12,15,15,18,21,119,0,0,1,0,66,0,229,4,143,3,125,0,17,0,0,1,33,21,33,23,7,39,35,23,7,1,53,1,23,7,51,55,23,2, +105,2,38,253,218,160,90,250,150,160,90,254,221,1,35,90,160,150,250,90,2,131,164,160,90,250,160,90,1,35,82,1,35,90,160,250,90,0,0,0,1,1,28,0,0,3,181,4,77,0,17,0,0,1,7,39,55,53,7,39,1,51,1,7,39,21,23,7,39,17,35,2,22,160,90,250,160,90,1,36,82,1,34,90,160, +250,90,160,164,2,38,160,90,250,150,160,90,1,35,254,221,90,160,150,250,90,160,253,218,0,0,0,1,0,66,0,229,4,143,3,125,0,17,0,0,1,39,55,23,51,39,55,1,21,1,39,55,35,7,39,55,33,53,2,104,160,90,250,150,160,90,1,35,254,221,90,160,150,250,90,160,253,218,2,131, +160,90,250,160,90,254,221,82,254,221,90,160,250,90,160,164,0,0,0,1,1,28,0,0,3,181,4,77,0,17,0,0,1,55,23,7,21,55,23,1,35,1,55,23,53,39,55,23,17,51,2,186,160,90,250,160,90,254,222,82,254,220,90,160,250,90,160,164,2,39,160,90,250,150,160,90,254,221,1,35, +90,160,150,250,90,160,2,38,0,0,0,1,0,66,0,229,4,143,3,125,0,14,0,0,1,23,7,39,33,23,7,1,53,1,23,7,33,55,23,3,157,242,90,250,253,228,160,90,254,221,1,35,90,160,2,28,250,90,2,49,242,90,250,160,90,1,35,82,1,35,90,160,250,90,0,1,0,66,0,229,4,143,3,125,0,14, +0,0,1,39,55,23,33,39,55,1,21,1,39,55,33,7,39,1,52,242,90,250,2,28,160,90,1,35,254,221,90,160,253,228,250,90,2,49,242,90,250,160,90,254,221,82,254,221,90,160,250,90,0,1,0,66,0,229,4,143,3,125,0,13,0,0,1,53,51,17,35,53,33,23,7,1,53,1,23,7,3,235,164,164, +253,52,160,90,254,221,1,35,90,160,2,131,250,253,104,250,160,90,1,35,82,1,35,90,160,0,0,0,0,1,1,28,0,0,3,181,4,77,0,13,0,0,37,17,7,39,1,51,1,7,39,17,51,21,33,53,2,22,160,90,1,36,82,1,34,90,160,250,253,104,164,2,204,160,90,1,35,254,221,90,160,253,52,164, +164,0,0,0,0,1,0,66,0,229,4,143,3,125,0,13,0,0,19,33,39,55,1,21,1,39,55,33,21,35,17,51,230,2,204,160,90,1,35,254,221,90,160,253,52,164,164,2,131,160,90,254,221,82,254,221,90,160,250,2,152,0,0,0,0,1,1,28,0,0,3,181,4,77,0,13,0,0,1,17,55,23,1,35,1,55,23, +17,35,53,33,21,2,186,160,90,254,222,82,254,220,90,160,250,2,152,3,169,253,52,160,90,254,221,1,35,90,160,2,204,164,164,0,0,0,1,1,28,0,0,3,181,4,77,0,19,0,0,37,39,55,23,17,7,39,1,51,1,7,39,17,55,23,7,51,21,33,53,2,22,250,90,160,160,90,1,36,82,1,34,90,160, +160,90,250,250,253,104,164,250,90,160,2,24,160,90,1,35,254,221,90,160,253,232,160,90,250,164,164,0,0,1,0,66,0,229,4,143,4,35,0,40,0,0,1,50,55,54,55,54,55,54,53,52,39,38,39,38,39,38,35,53,50,22,23,22,23,22,21,20,7,6,7,6,7,6,35,33,23,7,1,53,1,23,7,3,100, +30,26,23,19,17,10,10,9,10,18,16,26,23,25,62,98,45,42,22,22,21,20,44,37,58,48,31,253,147,160,90,254,221,1,35,90,160,2,131,10,9,18,17,23,24,25,27,21,23,18,16,11,10,164,42,43,40,53,52,60,56,53,50,46,38,26,21,160,90,1,35,82,1,35,90,160,0,0,0,0,1,0,66,0,229, +4,143,4,35,0,41,0,0,1,33,39,55,1,21,1,39,55,33,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,51,21,34,7,6,7,6,7,6,21,20,23,22,23,22,23,22,1,109,2,69,160,90,1,35,254,221,90,160,253,147,31,48,58,37,44,20,21,22,22,42,45,49,49,62,25,23,26,16,18,10,9,10,10, +17,19,23,26,2,131,160,90,254,221,82,254,221,90,160,21,26,38,46,50,53,56,60,52,53,40,43,21,21,164,10,11,16,18,23,21,27,25,24,23,17,18,9,10,0,0,0,0,2,0,66,0,229,4,143,4,35,0,36,0,62,0,0,1,50,22,23,22,23,22,21,20,7,6,7,6,7,6,43,1,21,35,53,33,23,7,1,53,1, +23,7,33,53,52,55,54,55,54,55,54,23,34,7,6,7,6,7,6,29,1,51,50,55,54,55,54,55,54,53,52,39,38,39,38,39,38,3,108,62,98,45,42,22,22,21,20,44,37,58,48,31,151,164,254,206,160,90,254,221,1,35,90,160,1,50,21,22,41,45,48,49,57,17,26,22,18,15,12,9,111,30,26,23, +19,17,10,10,9,10,18,16,26,23,4,35,42,43,40,53,52,60,56,53,50,46,38,26,21,213,213,160,90,1,35,82,1,35,90,160,125,59,52,55,40,43,21,20,163,10,10,17,15,27,22,26,125,10,9,18,17,23,24,25,27,21,23,18,16,11,10,0,0,0,0,2,0,66,0,229,4,143,4,35,0,36,0,62,0,0,1, +22,23,22,23,22,23,22,29,1,33,39,55,1,21,1,39,55,33,21,35,53,35,34,39,38,39,38,39,38,53,52,55,54,55,62,1,23,34,7,6,7,6,7,6,21,20,23,22,23,22,23,22,59,1,53,52,39,38,39,38,39,38,1,101,57,49,48,45,41,22,21,1,50,160,90,1,35,254,221,90,160,254,206,164,151, +31,48,58,37,44,20,21,22,22,42,45,98,62,25,23,26,16,18,10,9,10,10,17,19,23,26,30,111,9,12,15,18,22,26,4,35,1,20,21,43,40,55,52,59,125,160,90,254,221,82,254,221,90,160,213,213,21,26,38,46,50,53,56,60,52,53,40,43,42,164,10,11,16,18,23,21,27,25,24,23,17, +18,9,10,125,26,22,27,15,17,10,10,0,0,0,1,0,66,0,229,4,143,3,125,0,88,0,0,1,51,22,23,22,23,30,1,50,54,55,54,55,54,55,54,55,54,51,50,23,22,23,22,23,22,23,30,1,50,54,55,54,55,54,63,1,39,55,1,21,1,39,55,35,38,7,6,7,6,7,6,34,39,38,39,38,39,38,39,38,39,38, +34,7,6,7,6,7,6,7,6,7,6,34,39,38,39,38,39,38,7,35,23,7,1,53,1,23,1,31,8,33,24,24,25,7,16,19,16,7,7,4,11,22,23,26,27,31,33,25,30,19,22,11,3,7,7,17,18,17,7,30,19,23,26,15,160,90,1,35,254,221,90,160,6,12,6,9,7,27,21,27,62,27,27,22,25,8,3,7,7,9,8,19,8,8,7, +7,3,8,26,21,28,26,62,27,24,25,7,9,6,11,7,160,90,254,221,1,35,90,2,131,3,16,17,34,9,11,11,9,12,12,42,33,35,16,17,17,21,30,36,39,12,12,9,11,11,9,42,9,12,4,3,160,90,254,221,82,254,221,90,160,1,5,5,10,37,13,17,17,18,32,39,37,12,11,10,5,6,6,5,10,8,15,37,39, +32,18,17,17,16,34,10,5,5,1,160,90,1,35,82,1,35,90,0,0,1,0,66,0,209,4,143,3,145,0,23,0,0,1,33,3,39,55,35,23,7,1,53,1,23,7,33,19,23,7,51,39,55,1,21,1,39,3,178,254,232,60,140,50,229,160,90,254,221,1,35,90,160,1,6,60,140,50,247,160,90,1,35,254,221,90,1,223, +254,242,32,238,160,90,1,35,82,1,35,90,160,1,14,32,238,160,90,254,221,82,254,221,90,0,0,0,1,0,113,0,0,4,96,5,149,0,13,0,0,37,55,23,5,39,3,55,23,19,1,19,23,3,1,3,93,184,74,254,177,81,239,103,132,122,253,61,151,160,90,2,195,211,132,104,239,13,1,80,74,185, +2,212,254,86,3,125,30,253,236,1,170,0,0,0,1,0,183,0,0,4,26,5,101,0,11,0,0,1,23,7,1,53,1,23,7,33,17,35,17,1,148,160,90,254,222,1,34,90,160,2,134,164,3,199,160,90,1,35,82,1,35,90,160,251,149,3,199,0,0,0,1,0,183,0,0,4,26,5,101,0,11,0,0,1,33,17,35,17,33, +39,55,1,21,1,39,3,60,254,32,164,2,132,160,90,1,36,254,220,90,3,199,252,57,4,107,160,90,254,221,82,254,221,90,0,0,0,1,0,183,0,0,4,26,5,101,0,11,0,0,1,33,17,51,17,33,23,7,1,53,1,23,1,148,1,226,164,253,122,160,90,254,222,1,34,90,1,158,3,199,251,149,160, +90,1,35,82,1,35,90,0,0,0,1,0,183,0,0,4,26,5,101,0,11,0,0,1,39,55,1,21,1,39,55,33,17,51,17,3,60,160,90,1,36,254,220,90,160,253,124,164,1,158,160,90,254,221,82,254,221,90,160,4,107,252,57,0,0,0,1,0,186,0,0,4,23,4,82,0,11,0,0,37,17,33,53,33,17,55,23,1,35, +1,55,2,121,254,65,2,99,160,90,254,221,82,254,221,90,221,2,209,164,252,139,160,90,254,221,1,35,90,0,0,0,0,1,0,63,0,0,4,146,3,93,0,11,0,0,1,33,17,51,17,33,23,7,1,53,1,23,1,28,2,210,164,252,138,160,90,254,222,1,34,90,1,158,1,191,253,157,160,90,1,35,82,1, +35,90,0,0,0,1,0,81,1,88,4,128,3,229,0,41,0,0,1,55,54,55,54,55,54,55,54,51,50,23,22,23,22,23,22,23,35,52,39,38,39,38,39,38,7,6,7,6,7,6,7,6,23,21,55,23,1,35,1,55,1,75,1,1,36,30,60,57,74,71,84,87,68,76,55,58,32,30,1,152,19,19,37,35,48,40,55,57,41,46,37, +36,20,17,2,160,90,254,221,82,254,221,90,2,53,24,78,83,72,59,57,30,29,29,33,54,58,73,70,84,55,47,48,39,36,23,19,1,1,18,20,38,36,50,40,71,23,160,90,254,221,1,35,90,0,1,0,81,1,88,4,128,3,229,0,42,0,0,1,55,23,1,35,1,55,23,53,54,39,38,39,38,39,38,39,38,7, +6,7,6,7,6,21,48,35,54,55,54,55,54,55,54,51,50,23,22,23,22,23,22,23,3,134,160,90,254,221,82,254,221,90,160,2,17,20,36,37,46,41,57,55,40,48,35,37,19,19,152,1,30,32,58,55,76,68,87,84,71,74,57,60,30,36,1,2,53,160,90,254,221,1,35,90,160,23,71,40,50,36,38, +20,18,1,1,19,23,36,39,48,47,55,84,70,73,58,54,33,29,29,30,57,59,72,83,78,0,0,0,0,2,0,50,0,0,4,159,4,26,0,9,0,13,0,0,19,55,33,21,35,1,7,1,21,35,3,53,33,21,184,58,1,156,227,2,110,116,253,146,127,134,4,108,3,39,58,127,253,146,116,2,110,227,2,63,80,80,0, +0,0,2,0,66,0,0,4,143,4,214,0,13,0,27,0,0,19,1,23,7,33,21,33,23,7,1,17,35,17,51,1,17,51,17,35,17,1,39,55,33,53,33,39,55,230,1,35,90,160,2,204,253,52,160,90,254,221,164,164,3,5,164,164,254,221,90,160,253,52,2,204,160,90,3,179,1,35,90,160,164,160,90,1,35, +254,221,2,152,252,159,1,35,253,104,1,35,254,221,90,160,164,160,90,0,0,1,0,88,0,0,4,121,3,249,0,54,0,0,1,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,39,38,39,38,53,52,55,54,55,23,6,7,6,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,39,38,47,1,21,35,17,55,33, +21,3,149,29,74,37,37,37,39,72,68,95,83,108,104,88,91,72,74,37,37,37,37,74,119,52,24,25,50,50,45,65,56,144,59,62,49,49,50,25,30,45,33,127,58,1,156,3,122,29,74,90,91,103,104,88,92,72,67,43,37,37,39,71,75,89,91,101,103,91,87,77,115,50,61,62,70,68,123,50, +44,30,25,25,27,47,50,123,68,70,62,72,39,28,227,1,156,58,127,0,0,1,0,88,0,0,4,121,3,249,0,54,0,0,1,35,53,33,23,17,35,53,7,6,7,6,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,39,38,39,55,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,39,38,39,38,53,52,55,54,55,1, +60,227,1,156,58,127,33,45,30,25,50,49,49,62,59,144,56,65,45,50,50,25,24,52,119,74,37,37,37,37,74,72,91,88,104,108,83,95,68,72,39,38,38,38,73,3,122,127,58,254,100,227,28,39,72,62,70,68,123,50,47,27,25,25,30,44,50,123,68,70,62,61,50,115,77,87,91,103,101, +91,89,75,71,39,37,37,43,67,72,92,88,104,103,91,91,73,0,0,0,1,0,66,1,223,4,143,3,125,0,6,0,0,19,53,1,23,7,33,21,66,1,35,90,160,3,112,1,223,123,1,35,90,160,164,0,1,0,66,0,229,4,143,2,131,0,6,0,0,19,33,21,33,23,7,1,66,4,77,252,144,160,90,254,221,2,131,164, +160,90,1,35,0,0,0,0,1,2,22,0,0,3,181,4,77,0,6,0,0,1,51,1,7,39,17,35,2,22,124,1,34,90,160,164,4,77,254,221,90,160,252,144,0,0,0,0,1,1,28,0,0,2,187,4,77,0,6,0,0,1,17,35,17,7,39,1,2,186,164,160,90,1,36,4,77,251,179,3,112,160,90,1,35,0,0,0,1,0,66,1,223,4, +143,3,125,0,6,0,0,1,33,53,33,39,55,1,4,143,251,179,3,112,160,90,1,35,1,223,164,160,90,254,221,0,0,0,1,0,66,0,229,4,143,2,131,0,6,0,0,1,21,1,39,55,33,53,4,143,254,221,90,160,252,144,2,131,123,254,221,90,160,164,0,0,0,0,1,2,22,0,0,3,181,4,77,0,6,0,0,33, +17,51,17,55,23,1,2,22,164,160,90,254,222,4,77,252,144,160,90,254,221,0,1,1,71,0,0,2,229,4,77,0,6,0,0,33,35,1,55,23,17,51,2,229,123,254,221,90,160,164,1,35,90,160,3,112,0,0,2,0,66,0,0,4,143,4,124,0,9,0,19,0,0,9,1,39,55,33,53,33,39,55,9,1,53,1,23,7,33, +21,33,23,7,4,143,254,221,90,160,252,144,3,112,160,90,1,35,251,179,1,35,90,160,3,112,252,144,160,90,3,7,254,221,90,160,164,160,90,254,221,253,202,82,1,35,90,160,164,160,90,0,0,2,0,42,0,0,4,167,4,77,0,9,0,19,0,0,33,1,55,23,17,51,17,55,23,9,1,51,1,7,39, +17,35,17,7,39,3,50,254,220,90,160,164,160,90,254,222,253,202,82,1,34,90,160,164,160,90,1,35,90,160,3,112,252,144,160,90,254,221,4,77,254,221,90,160,252,144,3,112,160,90,0,0,0,0,2,0,66,0,0,4,143,4,124,0,9,0,19,0,0,1,21,1,39,55,33,53,33,39,55,37,1,23,7, +33,21,33,23,7,1,4,143,254,221,90,160,252,144,3,112,160,90,252,214,1,35,90,160,3,112,252,144,160,90,254,221,1,117,82,254,221,90,160,164,160,90,193,1,35,90,160,164,160,90,1,35,0,0,0,1,0,66,0,0,4,143,4,124,0,17,0,0,1,39,53,1,23,7,33,21,33,23,7,33,21,33, +23,7,1,53,1,11,201,1,35,90,160,3,112,252,144,160,160,3,112,252,144,160,90,254,221,2,62,201,82,1,35,90,160,164,160,160,164,160,90,1,35,82,0,0,0,1,0,42,0,0,4,167,4,77,0,17,0,0,1,55,51,1,7,39,17,35,17,7,39,17,35,17,7,39,1,51,2,104,202,82,1,34,90,160,164, +160,160,164,160,90,1,36,82,3,132,201,254,221,90,160,252,144,3,112,160,160,252,144,3,112,160,90,1,35,0,0,0,1,0,66,0,0,4,143,4,124,0,17,0,0,1,23,21,1,39,55,33,53,33,39,55,33,53,33,39,55,1,21,3,198,201,254,221,90,160,252,144,3,112,160,160,252,144,3,112, +160,90,1,35,2,62,201,82,254,221,90,160,164,160,160,164,160,90,254,221,82,0,0,0,1,0,42,0,0,4,167,4,77,0,17,0,0,37,7,35,1,55,23,17,51,17,55,23,17,51,17,55,23,1,35,2,104,200,82,254,220,90,160,164,160,160,164,160,90,254,222,82,201,201,1,35,90,160,3,112,252, +144,160,160,3,112,252,144,160,90,254,221,0,0,0,0,2,0,66,0,65,4,143,4,33,0,6,0,13,0,0,1,21,1,39,55,33,61,2,1,23,7,33,21,4,143,254,221,90,160,252,144,1,35,90,160,3,112,1,223,123,254,221,90,160,164,164,123,1,35,90,160,164,0,0,0,2,0,66,0,65,4,143,4,33,0, +6,0,13,0,0,19,33,21,33,23,7,9,1,33,53,33,39,55,1,66,4,77,252,144,160,90,254,221,4,77,251,179,3,112,160,90,1,35,1,223,164,160,90,1,35,1,31,164,160,90,254,221,0,0,2,0,66,0,229,4,143,3,125,0,21,0,26,0,0,1,33,55,23,7,51,21,33,7,33,21,33,7,39,55,35,23,7,1, +53,1,23,5,33,7,23,33,1,113,1,163,86,97,54,250,254,210,90,1,136,254,69,86,96,54,227,78,90,254,221,1,35,90,1,34,254,62,82,82,1,106,2,213,168,59,109,82,164,82,166,58,108,78,90,1,35,82,1,35,90,160,82,82,0,0,3,0,66,0,229,4,143,3,175,0,4,0,28,0,33,0,0,1,33, +7,23,51,55,51,39,55,1,21,1,39,55,35,7,39,55,35,23,7,1,53,1,23,7,51,55,23,3,7,33,55,39,2,33,254,254,82,82,223,200,154,78,90,1,35,254,221,90,78,227,31,140,27,124,78,90,254,221,1,35,90,78,194,46,140,57,35,1,33,82,82,2,131,82,82,246,78,90,254,221,82,254, +221,90,78,158,32,126,78,90,1,35,82,1,35,90,78,218,32,254,244,164,82,82,0,2,0,66,0,229,4,143,3,125,0,21,0,26,0,0,1,33,7,39,55,35,53,33,55,33,53,33,55,23,7,51,39,55,1,21,1,39,37,33,55,39,33,3,96,254,93,86,97,54,250,1,46,90,254,120,1,187,86,96,54,227,78, +90,1,35,254,221,90,254,222,1,194,82,82,254,150,1,141,168,59,109,82,164,82,166,58,108,78,90,254,221,82,254,221,90,160,82,82,0,0,1,0,66,0,229,4,143,3,125,0,14,0,0,1,7,23,33,21,33,23,7,1,53,1,23,7,33,21,1,31,82,82,3,112,252,226,78,90,254,221,1,35,90,78, +3,30,2,131,82,82,82,78,90,1,35,82,1,35,90,78,82,0,0,0,1,1,28,0,0,3,181,4,77,0,14,0,0,1,17,35,17,7,39,1,51,1,7,39,17,35,19,39,2,22,82,78,90,1,36,82,1,34,90,78,82,1,83,3,112,252,144,3,30,78,90,1,35,254,221,90,78,252,226,3,112,82,0,0,1,0,66,0,229,4,143, +3,125,0,14,0,0,1,33,53,33,39,55,1,21,1,39,55,33,53,33,55,3,178,252,144,3,30,78,90,1,35,254,221,90,78,252,226,3,112,82,2,131,82,78,90,254,221,82,254,221,90,78,82,82,0,0,0,1,1,28,0,0,3,181,4,77,0,14,0,0,37,3,51,17,55,23,1,35,1,55,23,17,51,17,23,2,187,1, +82,78,90,254,222,82,254,220,90,78,82,82,221,3,112,252,226,78,90,254,221,1,35,90,78,3,30,252,144,82,0,0,0,2,0,66,0,229,4,143,3,125,0,5,0,21,0,0,1,33,7,23,33,55,47,1,55,1,21,1,39,55,33,23,7,1,53,1,23,7,3,178,253,109,82,82,2,147,82,164,78,90,1,35,254,221, +90,78,254,17,78,90,254,221,1,35,90,78,2,131,82,82,82,164,78,90,254,221,82,254,221,90,78,78,90,1,35,82,1,35,90,78,0,0,0,2,1,28,0,0,3,181,4,77,0,5,0,21,0,0,1,39,7,17,23,55,19,17,55,23,1,35,1,55,23,17,7,39,1,51,1,7,2,187,83,82,82,83,81,78,90,254,222,82, +254,220,90,78,78,90,1,36,82,1,34,90,3,112,82,82,253,109,82,82,2,65,254,17,78,90,254,221,1,35,90,78,1,239,78,90,1,35,254,221,90,0,0,1,0,155,255,198,4,54,3,97,0,14,0,0,1,35,21,1,7,1,21,35,17,55,33,21,35,1,7,1,142,116,2,110,58,253,204,127,58,1,156,110,2, +51,58,2,226,116,253,146,58,2,53,112,1,156,58,127,253,204,58,0,0,0,0,1,0,155,255,198,4,54,3,97,0,14,0,0,9,1,39,1,35,53,33,23,17,35,53,1,39,1,53,3,67,253,146,58,2,51,110,1,156,58,127,253,204,58,2,110,2,226,253,146,58,2,52,127,58,254,100,112,253,203,58, +2,110,116,0,1,0,155,0,0,4,54,3,155,0,14,0,0,37,1,55,1,53,51,17,7,33,53,51,1,55,1,51,3,183,253,146,58,2,52,127,58,254,100,112,253,203,58,2,110,116,243,2,110,58,253,205,110,254,100,58,127,2,52,58,253,146,0,0,1,0,155,0,0,4,54,3,155,0,14,0,0,37,1,23,1,51, +21,33,39,17,51,21,1,23,1,21,1,142,2,110,58,253,205,110,254,100,58,127,2,52,58,253,146,127,2,110,58,253,204,127,58,1,156,112,2,53,58,253,146,116,0,0,1,0,66,0,229,4,143,3,125,0,15,0,0,1,7,1,53,1,23,33,21,33,7,33,21,33,23,33,21,1,191,90,254,221,1,35,90, +2,208,252,222,119,3,153,252,103,119,3,34,1,63,90,1,35,82,1,35,90,82,119,82,119,82,0,1,0,66,0,229,4,143,3,125,0,15,0,0,1,33,53,33,55,33,53,33,39,33,53,33,55,1,21,1,3,18,253,48,3,34,119,252,103,3,153,119,252,222,2,208,90,1,35,254,221,1,63,82,119,82,119, +82,90,254,221,82,254,221,0,1,0,66,0,229,4,143,3,125,0,22,0,0,1,51,23,55,23,55,23,55,51,21,7,39,7,39,7,39,35,23,7,1,53,1,23,1,31,129,58,151,150,150,150,59,33,92,150,150,150,151,91,96,160,90,254,221,1,35,90,2,131,67,173,173,173,173,67,164,106,173,173,173, +173,106,160,90,1,35,82,1,35,90,0,1,0,66,0,229,4,143,3,125,0,22,0,0,1,39,55,1,21,1,39,55,35,7,39,7,39,7,39,53,51,23,55,23,55,23,55,3,178,160,90,1,35,254,221,90,160,96,91,151,150,150,150,92,33,59,150,150,150,151,58,2,131,160,90,254,221,82,254,221,90,160, +106,173,173,173,173,106,164,67,173,173,173,173,67,0,0,0,0,1,1,28,0,0,3,181,4,77,0,25,0,0,37,21,35,53,35,53,51,53,35,53,51,53,7,39,1,51,1,7,39,21,51,21,35,21,51,21,2,186,164,250,250,250,250,160,90,1,36,82,1,34,90,160,250,250,250,188,188,188,164,116,164, +248,160,90,1,35,254,221,90,160,248,164,116,164,0,0,0,1,1,28,0,0,3,181,4,77,0,25,0,0,1,53,51,21,51,21,35,21,51,21,35,21,55,23,1,35,1,55,23,53,35,53,51,53,35,53,2,22,164,250,250,250,250,160,90,254,222,82,254,220,90,160,250,250,250,3,144,189,189,164,116, +164,247,160,90,254,221,1,35,90,160,247,164,116,164,0,0,3,0,66,0,229,4,143,3,125,0,9,0,13,0,17,0,0,1,21,33,23,7,1,53,1,23,7,5,53,51,21,51,53,51,21,2,33,254,254,160,90,254,221,1,35,90,160,1,127,187,123,187,2,131,164,160,90,1,35,82,1,35,90,160,164,164,164, +164,164,0,0,0,3,1,28,0,0,3,181,4,77,0,9,0,13,0,17,0,0,1,17,7,39,1,51,1,7,39,19,7,23,35,55,19,21,35,55,2,22,160,90,1,36,82,1,34,90,160,1,1,1,165,1,163,164,1,2,110,1,2,160,90,1,35,254,221,90,160,254,254,125,187,187,254,202,187,187,0,3,0,66,0,229,4,143, +3,125,0,9,0,13,0,17,0,0,1,33,39,55,1,21,1,39,55,33,43,1,53,51,5,35,53,51,2,176,1,2,160,90,1,35,254,221,90,160,254,254,125,187,187,254,202,187,187,2,131,160,90,254,221,82,254,221,90,160,164,164,164,0,0,3,1,28,0,0,3,181,4,77,0,9,0,13,0,17,0,0,1,17,55,23, +1,35,1,55,23,17,55,39,51,21,3,39,51,21,2,186,160,90,254,222,82,254,220,90,160,1,1,164,163,1,164,1,223,254,254,160,90,254,221,1,35,90,160,1,2,125,187,187,1,54,187,187,0,0,0,1,0,66,0,229,4,143,3,125,0,13,0,0,19,1,23,7,33,21,33,23,7,1,17,35,17,51,230,1, +35,90,160,2,204,253,52,160,90,254,221,164,164,2,90,1,35,90,160,164,160,90,1,35,254,221,2,152,0,0,0,1,0,66,0,229,4,143,3,125,0,13,0,0,1,17,51,17,35,17,1,39,55,33,53,33,39,55,3,235,164,164,254,221,90,160,253,52,2,204,160,90,2,90,1,35,253,104,1,35,254,221, +90,160,164,160,90,0,0,0,0,2,0,25,0,188,4,143,3,166,0,6,0,13,0,0,1,7,23,53,33,53,33,19,9,1,21,33,17,33,1,63,194,194,3,10,252,246,79,254,139,1,117,3,1,252,255,2,244,195,195,93,204,254,37,1,117,1,117,201,254,168,0,0,0,2,0,243,0,0,3,222,4,118,0,6,0,13,0, +0,1,51,17,51,17,51,39,1,35,17,33,17,35,1,1,166,92,204,94,196,1,118,202,254,168,200,1,116,3,80,252,246,3,10,194,254,239,252,255,3,1,1,117,0,0,2,0,66,0,188,4,185,3,166,0,6,0,13,0,0,1,21,33,21,33,21,55,1,53,33,17,33,53,1,3,146,252,246,3,10,194,254,240,252, +254,3,2,1,116,2,244,93,204,93,195,254,139,201,1,88,201,254,139,0,0,2,0,243,0,0,3,222,4,118,0,6,0,13,0,0,1,35,17,35,17,35,23,1,51,17,33,17,51,1,3,44,94,204,92,194,254,140,200,1,88,202,254,138,1,38,3,10,252,246,194,1,17,3,1,252,255,254,139,0,0,4,0,243, +0,0,3,222,4,118,0,6,0,10,0,14,0,21,0,0,1,17,51,39,7,51,25,1,21,51,53,37,33,17,33,25,1,35,9,1,35,17,2,206,94,196,194,92,204,254,238,1,88,254,168,200,1,116,1,118,202,1,224,1,112,194,194,254,144,254,242,140,140,70,254,232,1,154,1,103,1,117,254,139,254,153, +0,0,0,2,0,243,0,0,3,222,4,118,0,10,0,21,0,0,37,17,51,39,7,51,17,35,21,33,53,37,17,35,9,1,35,17,51,17,33,17,2,206,94,196,194,92,200,2,94,254,36,200,1,116,1,118,202,202,253,22,210,2,126,194,194,253,130,140,140,70,1,233,1,117,254,139,254,23,254,232,1,24, +0,3,0,243,0,0,3,222,4,118,0,11,0,14,0,25,0,0,1,35,7,51,17,35,21,33,53,35,17,51,47,1,7,3,17,35,9,1,35,17,51,17,33,17,2,224,240,74,92,200,2,94,202,94,124,72,71,101,200,1,116,1,118,202,202,253,22,3,154,74,253,130,140,140,2,126,123,71,71,253,77,1,233,1,117, +254,139,254,23,254,232,1,24,0,0,0,0,3,0,243,0,0,3,222,4,118,0,6,0,13,0,24,0,0,1,7,51,17,35,21,33,19,17,33,53,35,17,51,1,17,35,9,1,35,17,51,17,33,17,2,70,160,92,200,1,12,70,1,12,202,94,254,144,200,1,116,1,118,202,202,253,22,3,239,159,253,130,140,3,169, +252,87,140,2,126,253,200,1,233,1,117,254,139,254,23,254,232,1,24,0,0,0,0,3,0,243,0,0,3,222,4,118,0,6,0,12,0,23,0,0,1,51,39,7,51,17,51,3,51,39,7,51,55,7,35,9,1,35,23,35,17,33,17,35,2,206,94,196,194,92,204,8,102,196,194,100,94,172,200,1,116,1,118,202,202, +202,254,168,200,2,136,194,194,253,190,3,10,194,194,94,173,1,117,254,139,200,253,199,2,57,0,3,0,243,0,0,3,222,4,118,0,10,0,16,0,31,0,0,1,17,35,21,33,53,35,17,51,39,7,37,51,39,7,51,55,3,35,55,35,9,1,35,23,35,17,51,17,33,17,51,2,2,200,2,94,202,94,196,194, +1,32,102,196,194,100,94,172,200,200,200,1,116,1,118,202,202,202,202,253,22,200,2,136,254,74,140,140,1,182,194,194,200,194,194,94,254,139,200,1,117,254,139,200,254,223,254,232,1,24,0,0,0,0,2,0,66,0,188,4,185,3,166,0,10,0,21,0,0,1,39,35,17,51,53,33,21, +55,39,21,1,21,33,17,33,21,33,53,9,1,53,1,21,1,140,140,2,126,194,194,253,200,254,232,1,24,1,234,1,116,254,140,2,151,201,253,162,201,93,195,195,93,254,238,201,2,234,201,201,254,139,254,139,201,0,0,0,0,2,0,69,0,0,4,140,4,70,0,9,0,15,0,0,1,55,33,21,35,1, +7,1,21,35,1,21,33,17,35,17,1,42,58,1,156,227,2,110,116,253,146,127,3,97,252,4,73,3,39,58,127,253,146,116,2,110,227,2,187,73,252,3,4,70,0,0,0,2,0,69,0,0,4,140,4,70,0,9,0,15,0,0,37,33,53,51,1,55,1,53,51,17,19,17,33,53,33,17,3,108,254,100,228,253,146,116, +2,110,126,230,251,186,3,252,229,127,2,110,116,253,146,227,254,100,3,38,251,187,73,3,252,0,0,0,0,2,0,243,0,0,3,222,4,118,0,9,0,19,0,0,1,17,35,23,55,35,17,51,39,7,23,35,9,1,35,17,51,9,1,51,2,2,92,194,196,94,94,196,194,22,200,1,116,1,118,202,202,254,138, +254,140,200,3,80,253,214,194,194,2,42,194,194,79,1,117,254,139,254,116,254,139,1,117,0,0,3,0,66,0,229,4,143,3,125,0,30,0,39,0,48,0,0,1,6,7,6,35,34,39,38,39,35,53,51,54,55,54,51,50,22,23,22,23,22,23,51,39,55,1,21,1,39,55,37,38,39,38,35,34,7,6,7,5,33,22, +23,22,51,50,55,54,2,197,19,52,82,118,120,78,49,18,107,107,19,50,79,119,57,103,39,32,28,6,4,237,160,90,1,35,254,221,90,160,254,153,11,17,48,71,68,50,18,11,1,38,254,219,12,15,43,74,68,53,17,1,223,64,51,80,79,50,66,164,66,52,82,44,40,32,58,12,14,160,90, +254,221,82,254,221,90,160,164,20,17,49,49,17,20,164,19,17,47,48,16,0,2,0,42,0,0,4,167,4,77,0,9,0,19,0,0,33,35,1,55,23,17,51,17,55,23,19,1,7,39,17,35,17,7,39,1,1,160,82,254,220,90,160,164,160,90,194,1,34,90,160,164,160,90,1,36,1,35,90,160,3,112,252,144, +160,90,3,42,254,221,90,160,252,144,3,112,160,90,1,35,0,1,0,66,255,1,4,143,5,97,0,25,0,0,1,55,33,53,33,39,55,33,53,33,39,55,1,21,7,23,21,7,23,21,1,39,55,33,53,33,3,18,160,252,144,3,112,160,160,252,144,3,112,160,90,1,35,201,201,201,201,254,221,90,160,252, +144,3,112,1,63,160,164,160,160,164,160,90,254,221,82,201,201,82,201,201,82,254,221,90,160,164,0,1,0,66,0,229,4,143,3,125,0,17,0,0,1,21,35,53,33,23,7,1,53,1,23,7,33,53,51,21,33,21,3,30,164,254,165,160,90,254,221,1,35,90,160,1,91,164,1,113,1,223,250,250, +160,90,1,35,82,1,35,90,160,250,250,164,0,0,0,1,0,66,0,229,4,143,3,125,0,17,0,0,1,33,53,33,53,51,21,33,39,55,1,21,1,39,55,33,21,35,1,178,254,144,1,112,164,1,92,160,90,1,35,254,221,90,160,254,164,164,1,223,164,250,250,160,90,254,221,82,254,221,90,160,250, +0,0,1,0,66,0,229,4,143,3,125,0,23,0,0,1,35,23,7,1,53,1,23,7,51,53,51,21,51,39,55,1,21,1,39,55,35,21,35,2,22,247,160,90,254,221,1,35,90,160,247,164,248,160,90,1,35,254,221,90,160,248,164,1,223,160,90,1,35,82,1,35,90,160,250,250,160,90,254,221,82,254,221, +90,160,250,0,0,0,0,1,0,66,0,229,4,143,3,125,0,25,0,0,1,21,35,53,35,21,35,53,35,23,7,1,53,1,23,7,51,53,51,21,51,53,51,21,51,21,3,210,164,116,164,247,160,90,254,221,1,35,90,160,247,164,116,164,189,1,223,250,250,250,250,160,90,1,35,82,1,35,90,160,250,250, +250,250,164,0,0,1,0,66,0,229,4,143,3,125,0,25,0,0,19,35,53,51,53,51,21,51,53,51,21,51,39,55,1,21,1,39,55,35,21,35,53,35,21,35,254,188,188,164,116,164,248,160,90,1,35,254,221,90,160,248,164,116,164,1,223,164,250,250,250,250,160,90,254,221,82,254,221,90, +160,250,250,250,0,0,0,1,0,66,0,229,4,143,3,125,0,31,0,0,1,23,7,1,53,1,23,7,51,53,51,21,51,53,51,21,51,39,55,1,21,1,39,55,35,21,35,53,35,21,35,53,1,31,160,90,254,221,1,35,90,160,167,134,56,134,168,160,90,1,35,254,221,90,160,168,134,56,134,1,223,160,90, +1,35,82,1,35,90,160,250,250,250,250,160,90,254,221,82,254,221,90,160,250,250,250,250,0,0,0,0,2,0,25,0,188,4,143,3,166,0,2,0,9,0,0,1,7,23,19,33,21,33,17,9,1,1,63,194,194,79,3,1,252,255,254,139,1,117,2,244,195,195,1,21,164,254,221,1,117,1,117,0,2,0,66, +0,188,4,184,3,166,0,2,0,9,0,0,1,17,55,37,17,9,1,17,33,53,3,146,194,254,239,1,117,254,139,252,255,2,244,254,122,195,82,1,35,254,139,254,139,1,35,164,0,3,0,25,0,188,4,184,3,166,0,2,0,5,0,15,0,0,1,7,23,1,17,55,5,17,9,1,17,33,17,9,1,17,1,63,194,194,2,83, +194,253,58,254,139,1,117,1,181,1,117,254,139,2,244,195,195,1,134,254,122,195,82,254,221,1,117,1,117,254,221,1,35,254,139,254,139,1,35,0,0,2,0,37,0,0,4,172,5,213,0,2,0,10,0,0,37,19,33,19,1,51,19,33,19,51,1,2,104,213,254,86,91,254,55,209,108,2,11,110,209, +254,55,178,2,252,252,82,5,213,254,123,1,133,250,43,0,1,0,117,255,227,4,92,5,240,0,25,0,0,18,16,0,32,23,22,23,35,38,39,38,35,34,2,16,18,51,50,55,54,55,51,6,7,6,32,117,1,9,1,246,133,66,33,202,18,27,79,157,156,157,157,156,157,79,27,18,202,33,66,133,254, +10,1,111,2,244,1,141,198,99,144,73,55,153,254,205,253,152,254,205,153,55,73,144,99,197,0,0,2,0,182,255,227,4,27,5,76,0,32,0,48,0,0,5,34,39,38,53,52,55,54,51,50,23,22,23,54,53,52,39,38,35,34,7,53,54,51,32,23,22,21,20,7,2,7,6,1,20,23,22,51,50,55,54,55, +54,55,38,35,34,7,6,2,12,141,92,109,96,99,178,117,92,54,37,13,32,71,188,71,110,116,104,1,12,114,53,25,63,163,128,254,193,44,47,72,64,51,72,53,44,22,89,154,132,58,36,29,85,101,183,190,148,152,73,43,72,81,92,135,78,173,44,168,31,246,116,173,113,131,254, +184,156,122,1,83,100,54,57,45,62,101,83,89,215,174,108,0,0,0,0,1,0,178,0,0,4,29,5,213,0,11,0,0,55,33,17,33,53,33,17,33,53,33,17,33,178,2,180,253,76,2,180,253,76,3,107,252,149,170,1,236,170,1,235,170,250,43,0,3,0,178,255,162,4,29,6,53,0,19,0,23,0,27,0, +0,1,17,33,7,35,55,35,53,51,19,33,53,33,19,33,53,33,55,51,15,1,3,51,17,1,3,33,17,4,29,253,138,27,154,26,90,138,139,254,235,1,68,138,254,50,1,254,27,155,28,47,138,213,254,251,138,1,143,5,213,250,43,94,94,170,1,236,170,1,235,170,96,96,170,254,21,1,235,253, +107,254,20,1,236,0,0,0,3,0,73,0,98,4,138,4,163,0,33,0,48,0,63,0,0,1,23,7,22,23,22,21,20,7,6,7,14,1,34,39,38,39,7,39,55,38,39,38,53,52,55,54,55,62,1,50,23,22,23,6,34,7,6,7,14,1,21,20,23,22,23,1,38,39,23,1,22,23,22,50,55,54,55,62,1,53,52,39,38,4,38,99, +118,45,26,39,39,39,79,79,190,221,95,64,56,118,99,117,45,27,39,39,39,79,79,190,221,95,65,58,247,163,71,69,58,59,57,28,17,26,2,40,36,40,175,253,216,35,38,71,163,70,70,58,59,57,28,16,4,162,99,118,56,64,95,112,109,95,95,79,78,80,40,26,45,118,99,117,58,65, +95,109,112,95,95,79,79,80,40,28,45,28,30,30,57,59,140,83,80,70,40,36,2,40,26,17,142,253,216,25,16,30,30,30,57,59,140,80,83,70,39,0,2,255,250,0,0,4,217,5,143,0,3,0,6,0,79,64,42,4,105,5,4,2,3,2,6,105,3,3,2,5,105,0,1,0,4,105,6,4,1,1,0,66,4,1,5,249,1,251, +0,6,5,4,2,1,5,7,3,0,7,16,212,204,17,23,57,49,0,47,228,236,17,57,48,75,83,88,7,16,8,237,7,16,5,237,7,16,5,237,7,16,8,237,89,34,35,1,51,9,2,33,6,2,6,209,2,8,253,143,254,144,2,225,5,143,250,113,4,195,251,233,0,0,0,0,2,255,250,0,0,4,217,5,143,0,3,0,6,0,0, +3,33,1,35,55,1,33,6,4,223,253,248,209,104,1,113,253,31,5,143,250,113,204,4,23,0,0,0,0,1,0,129,0,0,4,80,5,184,0,26,0,0,1,22,23,30,1,51,33,21,33,34,38,2,16,18,54,51,33,21,33,34,7,6,7,6,7,33,21,1,48,8,34,44,152,90,1,216,254,40,136,232,134,134,232,136,1, +216,254,40,92,74,78,42,34,8,3,30,2,135,102,95,130,150,170,196,1,81,1,142,1,81,196,170,75,77,128,95,102,170,0,3,0,129,255,79,4,80,6,105,0,28,0,37,0,43,0,0,37,22,51,33,21,33,34,39,7,39,55,38,39,38,16,18,54,59,1,55,23,7,51,21,35,3,33,21,33,19,35,34,7,6, +7,6,7,33,7,35,22,23,22,23,2,76,21,23,1,216,254,40,48,44,58,163,67,121,69,66,134,232,136,170,54,163,39,124,176,144,1,62,254,142,18,118,92,74,75,45,34,8,1,46,52,250,8,34,36,58,174,4,170,12,189,49,221,99,172,169,1,142,1,81,196,177,50,127,170,254,35,170, +2,135,75,75,130,95,102,170,102,95,108,70,0,0,0,1,0,130,0,165,4,79,4,93,0,23,0,66,0,176,8,47,176,9,51,176,10,51,177,5,4,237,177,6,4,237,177,7,4,237,176,1,176,5,16,222,176,2,50,177,0,4,237,177,23,4,237,176,18,176,0,16,222,176,19,50,176,20,50,177,15,4,237, +177,16,4,237,177,17,4,237,1,48,49,1,21,33,22,23,22,51,33,21,33,34,46,1,16,62,1,51,33,21,33,34,7,6,7,4,78,252,237,22,61,99,133,1,216,254,40,136,230,134,134,230,136,1,216,254,40,133,99,61,22,2,214,170,73,57,91,170,127,220,1,2,220,127,170,91,57,73,0,0,1, +0,129,0,0,4,80,5,184,0,26,0,0,1,38,39,46,1,35,33,53,33,50,22,18,16,2,6,35,33,53,33,50,55,54,55,54,55,33,53,3,160,8,32,44,152,90,254,40,1,216,136,232,134,134,232,136,254,40,1,216,92,74,76,44,32,8,252,226,3,49,102,95,130,150,170,196,254,175,254,114,254, +175,196,170,75,77,128,95,102,170,0,3,0,129,255,79,4,80,6,105,0,28,0,37,0,43,0,0,1,38,35,33,53,33,50,23,55,23,7,22,23,22,16,2,6,43,1,7,39,55,35,53,51,19,33,53,33,3,51,50,55,54,55,54,55,33,55,51,38,39,38,39,2,133,21,22,254,40,1,216,47,45,57,163,67,121, +68,68,134,232,136,171,54,163,39,123,174,146,254,192,1,114,18,120,92,74,74,46,32,8,254,211,52,249,8,32,37,58,5,10,4,170,12,189,49,221,99,172,169,254,114,254,175,196,177,50,127,170,1,221,170,253,121,75,75,130,95,102,170,102,95,108,70,0,0,1,0,130,0,165, +4,79,4,93,0,23,0,0,19,53,33,38,39,38,35,33,53,33,50,30,1,16,14,1,35,33,53,33,50,55,54,55,131,3,19,22,62,98,134,254,40,1,216,136,230,134,134,230,136,254,40,1,216,134,98,62,22,2,44,170,73,57,91,170,127,220,254,254,220,127,170,91,57,73,0,1,0,250,0,0,3,215, +5,4,0,3,0,0,51,17,33,17,250,2,221,5,4,250,252,0,0,0,0,1,0,152,254,76,4,57,5,238,0,7,0,31,185,0,5,1,15,64,11,1,3,0,8,4,128,2,6,128,0,8,16,212,236,212,236,49,0,16,196,50,212,236,48,19,17,33,17,35,17,33,17,152,3,161,155,253,149,254,76,7,162,248,94,7,30, +248,226,0,0,0,0,1,0,152,254,76,4,57,5,238,0,7,0,0,1,17,33,17,51,17,33,17,4,57,252,95,155,2,107,5,238,248,94,7,162,248,226,7,30,0,0,1,0,143,254,76,4,61,5,238,0,11,0,55,180,11,5,12,9,0,191,1,15,0,2,0,9,1,15,0,7,1,14,0,2,1,16,64,11,12,11,10,8,5,0,5,1,6, +3,12,16,212,60,196,23,57,49,0,16,228,244,236,16,238,17,18,57,57,48,1,33,21,33,53,9,1,53,33,21,33,1,1,76,2,241,252,82,2,37,253,219,3,154,253,35,2,10,254,213,137,92,3,151,3,80,95,140,252,221,0,0,0,0,1,0,88,2,45,4,121,2,215,0,3,0,17,182,0,160,2,4,1,0,4, +16,212,196,49,0,16,212,236,48,19,33,21,33,88,4,33,251,223,2,215,170,0,0,2,0,88,0,0,4,121,4,147,0,3,0,15,0,0,1,33,53,33,1,17,33,53,33,17,51,17,33,21,33,17,4,121,251,223,4,33,253,155,254,68,1,188,168,1,189,254,67,3,233,170,251,109,1,73,170,1,76,254,180, +170,254,183,255,255,0,102,255,66,4,55,5,213,16,6,0,18,0,0,255,255,0,166,0,175,4,43,4,85,16,7,0,13,0,0,254,101,0,0,255,255,1,43,1,71,3,166,3,194,16,7,0,114,0,0,253,210,0,0,255,255,1,63,1,154,3,145,3,234,16,6,7,45,0,201,0,1,0,59,255,217,4,160,6,160,0,10, +0,47,64,26,10,3,2,1,0,5,11,5,4,8,6,11,10,9,8,7,4,3,2,7,5,0,11,5,1,11,16,212,196,18,57,17,23,57,49,0,16,212,196,192,192,18,23,57,48,19,39,37,19,1,51,21,35,1,35,3,100,41,1,35,219,1,211,148,47,254,6,127,246,2,221,125,98,253,37,5,191,131,249,188,3,57,0,0, +255,255,0,59,255,217,4,160,7,118,16,39,0,117,255,101,1,134,18,6,8,52,0,0,255,255,0,59,255,217,4,160,7,101,16,39,7,72,255,101,1,134,18,6,8,52,0,0,0,2,0,186,0,250,4,23,3,240,0,11,0,37,0,0,1,46,1,35,34,6,21,20,22,51,50,54,1,34,38,39,14,1,35,34,38,53,52, +54,51,50,22,23,62,1,51,21,34,6,7,30,1,51,2,170,56,92,60,72,90,82,68,68,106,1,154,80,128,78,66,132,84,126,166,158,132,94,136,56,46,148,90,56,104,46,56,92,58,2,123,134,99,133,106,109,129,118,254,253,100,131,124,107,214,165,173,206,115,129,117,127,140,117, +124,136,100,0,0,0,0,3,0,41,0,250,4,168,3,240,0,11,0,23,0,47,0,55,64,28,36,24,9,21,3,225,39,33,226,15,9,225,45,27,223,48,12,0,36,24,18,6,100,30,18,100,42,48,16,212,236,212,236,17,57,57,57,57,49,0,16,252,60,236,50,252,60,236,50,17,57,57,48,1,30,1,51,50, +54,53,52,38,35,34,6,7,46,1,35,34,6,21,20,22,51,50,54,19,62,1,51,50,22,21,20,6,35,34,38,39,14,1,35,34,38,53,52,54,51,50,22,2,182,57,91,61,71,91,84,70,66,105,203,56,92,61,71,91,83,68,67,106,126,47,147,91,119,172,163,126,83,128,78,65,132,85,125,166,157, +132,94,136,2,115,136,100,134,108,107,128,117,116,134,99,133,106,109,129,118,0,255,117,127,219,160,167,212,100,131,124,107,214,165,173,206,115,0,1,0,125,1,31,4,84,4,245,0,5,0,0,1,33,17,51,17,33,4,84,252,42,170,3,44,1,31,3,214,252,212,0,0,0,0,1,0,125,1, +31,4,84,4,245,0,5,0,0,1,33,1,51,1,33,4,84,252,42,3,24,170,253,112,2,164,1,31,3,214,252,212,0,0,0,255,255,2,18,254,29,2,190,6,29,18,6,0,95,0,0,0,1,0,164,0,0,4,44,4,162,0,6,0,0,51,1,51,1,35,9,1,164,1,78,237,1,77,191,254,251,254,251,4,162,251,94,3,172,252, +84,0,1,0,164,0,0,4,44,4,162,0,6,0,0,19,51,9,1,51,1,35,164,191,1,5,1,5,191,254,179,237,4,162,252,84,3,172,251,94,0,0,1,0,164,0,0,4,44,4,162,0,36,0,0,19,52,55,54,55,54,55,54,51,50,22,23,22,23,22,21,17,35,17,52,39,38,39,38,39,38,35,34,7,6,7,6,7,6,21,17, +35,164,25,26,59,57,95,85,105,106,170,66,57,29,24,172,12,10,7,29,75,71,76,86,60,83,21,13,4,12,173,2,68,230,98,103,58,56,32,29,58,59,51,108,92,238,253,188,2,162,93,65,57,14,57,32,30,30,41,48,33,38,112,48,253,96,0,1,0,164,0,0,4,44,4,162,0,36,0,0,19,17,51, +17,20,23,22,23,22,23,22,51,50,55,54,55,54,55,54,53,17,51,17,20,7,6,7,14,1,35,34,39,38,39,38,39,38,164,173,12,4,13,21,83,60,86,76,71,75,29,7,10,12,172,24,29,57,66,170,106,105,85,95,57,59,26,25,2,94,2,68,253,96,48,112,38,33,48,41,30,30,32,57,14,57,65,93, +2,162,253,188,238,92,108,51,59,58,29,32,56,58,103,98,0,0,0,0,1,0,129,254,137,4,80,6,248,0,23,0,26,64,5,12,13,6,1,0,47,60,252,60,49,0,64,6,5,140,10,22,140,17,47,236,47,236,48,5,17,52,55,54,55,54,23,7,38,7,6,21,17,20,7,6,7,6,39,55,22,55,54,2,12,94,65,145, +134,142,106,92,78,120,93,65,145,134,142,106,92,78,119,68,6,34,106,100,69,7,6,113,113,67,3,5,146,249,222,106,100,69,7,6,113,113,67,3,5,0,0,0,2,0,63,254,124,4,145,7,5,0,23,0,47,0,0,5,17,52,55,54,51,50,23,7,38,7,6,21,3,20,7,6,35,34,39,55,22,55,54,37,19, +52,55,54,51,50,23,7,38,7,6,21,17,20,7,6,35,34,39,55,22,55,54,2,228,57,67,109,106,90,67,67,58,53,1,57,67,109,106,90,67,77,48,54,254,80,1,57,67,109,106,90,67,67,58,54,57,67,109,106,90,67,77,48,53,68,6,34,98,92,105,57,127,38,10,9,155,249,222,98,92,105,57, +127,43,15,17,147,6,34,98,92,105,57,127,38,10,9,155,249,222,98,92,105,57,127,43,15,17,0,0,0,3,0,53,254,151,4,157,6,234,0,23,0,47,0,71,0,0,5,17,52,55,54,55,54,23,7,38,35,34,21,17,20,7,6,7,6,39,55,22,51,50,37,17,52,55,54,55,54,23,7,38,35,34,21,17,20,7,6, +7,6,39,55,22,51,50,37,17,52,55,54,55,54,23,7,38,35,34,21,17,20,7,6,7,6,39,55,22,51,50,3,82,49,45,113,50,74,36,34,50,27,50,45,113,50,74,36,34,50,28,254,188,49,45,113,50,74,36,34,50,27,50,45,113,50,74,36,34,50,28,254,186,50,45,113,50,74,36,34,50,28,49, +45,113,50,74,36,34,50,27,127,6,93,109,83,74,2,1,29,142,14,78,249,163,111,81,74,2,1,29,142,14,78,6,93,109,83,74,2,1,29,142,14,78,249,163,111,81,74,2,1,29,142,14,78,6,93,109,83,74,2,1,29,142,14,78,249,163,111,81,74,2,1,29,142,14,255,255,0,187,0,134,4,25, +4,132,16,39,8,182,255,255,1,36,16,39,8,182,254,210,254,87,16,7,8,182,1,52,254,87,0,0,255,255,0,188,0,134,4,21,4,132,16,39,8,182,0,3,254,87,16,39,8,182,254,211,1,36,16,7,8,182,1,48,1,36,0,0,255,255,1,232,0,134,2,232,4,132,16,39,8,182,0,3,254,87,16,7,8, +182,255,255,1,36,0,0,255,255,0,187,0,134,4,25,4,132,16,39,8,182,254,210,254,87,16,39,8,182,254,211,1,36,16,39,8,182,1,52,254,87,16,7,8,182,1,48,1,36,0,0,255,255,0,88,2,45,4,121,4,132,16,38,8,46,0,0,16,7,8,182,0,2,1,36,0,3,0,74,0,134,4,135,4,132,0,3,0, +7,0,11,0,0,1,51,17,35,3,51,17,35,1,33,21,33,3,139,252,252,2,252,252,252,193,2,234,253,22,4,132,254,207,254,100,254,207,2,81,170,0,0,255,255,0,87,0,134,4,125,4,132,16,38,8,46,0,0,16,39,8,182,1,148,1,36,16,39,8,182,1,152,254,87,16,39,8,182,254,111,1,36, +16,7,8,182,254,110,254,87,255,255,0,88,0,134,4,121,4,132,16,38,8,75,0,0,16,39,8,182,0,2,1,36,16,7,8,182,0,1,254,87,0,1,0,88,1,241,4,121,3,18,0,27,0,0,1,21,14,1,35,34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,22,23,22,23,22,51,50,54,4,121,75,143,79,90,113, +22,11,77,103,51,79,141,73,78,146,83,53,100,75,10,22,116,93,70,137,3,18,175,59,55,51,10,4,34,24,59,64,174,60,55,22,32,4,11,54,60,0,0,0,1,0,88,1,241,4,121,3,18,0,27,0,0,19,30,1,51,50,55,54,55,62,1,51,50,22,23,21,46,1,35,34,6,7,6,7,6,35,34,38,39,88,74,137, +70,93,116,22,10,75,100,53,83,146,78,73,141,79,51,103,77,11,22,113,90,79,143,75,3,18,63,60,54,11,4,32,22,55,60,174,64,59,24,34,4,10,51,55,59,0,0,0,1,0,88,0,174,4,121,4,71,0,31,0,0,1,38,39,38,35,34,6,7,53,62,1,51,50,23,22,23,19,23,3,22,51,50,54,55,21,14, +1,35,34,39,3,39,2,24,29,23,52,51,79,141,73,78,146,83,54,49,45,29,78,136,83,88,73,70,137,74,75,143,79,81,100,83,136,2,80,11,5,12,59,64,174,60,55,11,11,12,1,87,31,254,145,34,60,63,175,59,55,41,254,148,31,0,0,0,0,2,0,88,1,49,4,121,3,162,0,3,0,29,0,0,19, +33,21,33,5,21,14,1,35,34,47,1,46,1,35,34,6,7,53,62,1,51,50,23,51,23,22,51,50,54,88,4,33,251,223,4,33,75,143,79,90,113,33,83,99,49,78,141,74,79,146,82,96,130,1,33,116,93,68,138,3,162,170,164,176,59,56,51,15,36,23,60,65,174,62,55,55,15,55,61,0,2,0,88,1, +96,4,121,3,195,0,3,0,31,0,0,19,33,21,33,1,21,14,1,35,34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,22,23,22,23,22,51,50,54,88,4,33,251,223,4,33,75,143,79,90,113,22,11,77,103,51,79,141,73,78,146,83,53,100,75,10,22,116,93,70,137,2,12,172,2,99,175,59,55,51,10, +4,34,24,59,64,174,60,55,22,32,4,11,54,60,0,1,0,88,0,98,4,122,4,213,0,39,0,0,1,3,22,55,54,55,21,6,7,6,35,34,39,7,33,21,33,7,39,55,35,53,33,55,38,39,38,7,6,7,53,54,55,54,55,54,31,2,19,3,199,167,102,89,85,69,53,107,73,81,37,92,110,2,42,253,120,152,114,89, +233,1,81,146,77,111,73,70,92,60,91,69,84,70,82,130,13,29,198,4,113,254,224,19,36,34,66,178,50,40,26,30,178,171,254,100,154,171,231,37,5,4,31,40,57,172,76,19,22,2,3,53,5,16,1,88,0,0,0,3,0,88,0,192,4,121,4,143,0,3,0,7,0,36,0,0,19,33,21,33,21,33,21,33,1, +21,14,1,35,34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,23,22,23,22,23,22,51,50,54,88,4,33,251,223,4,33,251,223,4,33,75,143,79,90,113,22,11,77,103,51,79,141,73,78,146,83,53,50,39,86,10,22,116,93,70,137,2,216,172,192,172,3,207,175,59,55,51,10,4,34,24,59,64, +174,60,55,11,9,34,4,11,54,60,0,0,2,0,88,0,49,4,121,4,143,0,19,0,48,0,0,37,35,53,33,55,33,53,33,55,23,7,51,21,33,7,33,21,33,7,39,1,21,14,1,35,34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,23,22,23,22,23,22,51,50,54,1,81,249,1,117,139,254,0,2,123,104,113,44, +249,254,139,139,2,0,253,132,103,113,3,84,75,143,79,90,113,22,11,77,103,51,79,141,73,78,146,83,53,50,39,86,10,22,116,93,70,137,192,172,192,172,143,82,61,172,192,172,143,82,4,12,175,59,55,51,10,4,34,24,59,64,174,60,55,11,9,34,4,11,54,60,0,0,0,1,0,88,0, +0,4,121,5,46,0,49,0,0,37,33,53,33,55,33,53,33,55,38,39,46,1,35,34,6,7,53,62,1,51,50,23,22,31,1,55,23,7,22,51,50,54,55,21,14,1,35,34,39,7,33,21,33,7,33,21,33,7,39,1,104,254,240,1,77,69,254,110,1,208,75,9,6,77,103,51,79,141,73,78,146,83,53,50,51,74,58, +86,155,81,11,12,70,137,74,75,143,79,31,33,56,1,161,254,33,69,2,36,253,159,70,156,192,172,192,172,209,4,2,34,24,59,64,174,60,55,11,11,32,25,238,56,225,1,60,63,175,59,55,6,156,172,192,172,192,55,0,0,2,0,88,1,49,4,121,3,195,0,27,0,55,0,75,64,38,29,39,32, +49,48,43,3,53,28,1,11,4,15,25,11,160,18,0,25,160,14,4,42,32,160,53,39,160,46,28,56,49,48,28,0,42,14,56,16,212,60,196,50,57,57,49,0,16,212,60,236,212,236,50,220,60,252,212,60,236,18,57,17,18,57,17,18,23,57,17,18,57,48,1,21,14,1,35,34,39,38,39,46,1,35, +34,6,7,53,62,1,51,50,22,23,22,23,22,51,50,54,19,21,14,1,35,34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,23,51,22,23,22,51,50,54,4,121,75,143,79,90,113,22,11,77,103,51,79,141,73,78,146,83,53,100,75,10,22,116,93,70,137,74,75,143,79,90,113,22,11,83,99,49,78, +141,74,79,146,82,96,130,1,11,22,116,93,68,138,3,195,175,59,55,51,10,4,34,24,59,64,174,60,55,22,32,4,11,54,60,254,208,176,59,56,51,10,5,36,23,60,65,174,62,55,55,5,10,55,61,0,0,0,0,1,0,88,0,48,4,121,4,195,0,56,0,0,1,38,35,34,6,7,53,62,1,51,50,23,55,38, +39,38,35,34,6,7,53,62,1,51,50,23,22,23,19,23,3,22,51,50,54,55,21,14,1,35,34,39,7,22,51,50,54,55,21,14,1,35,34,47,1,3,39,1,221,48,48,78,141,74,79,146,82,58,71,54,55,39,52,51,79,141,73,78,146,83,53,50,48,78,93,138,97,57,49,70,137,74,75,143,79,63,74,52, +114,91,68,138,75,75,143,79,100,103,31,98,138,1,163,11,60,65,174,62,55,20,178,22,9,12,59,64,174,60,55,11,11,33,1,55,41,254,189,15,60,63,175,59,55,25,175,53,61,64,176,59,56,51,16,254,188,41,0,0,0,3,0,88,0,192,4,121,4,147,0,27,0,55,0,59,0,0,1,21,14,1,35, +34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,22,23,22,23,22,51,50,54,19,21,14,1,35,34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,23,51,22,23,22,51,50,54,1,33,21,33,4,121,75,143,79,90,113,22,11,77,103,51,79,141,73,78,146,83,53,100,75,10,22,116,93,70,137,74,75, +143,79,90,113,22,11,83,99,49,78,141,74,79,146,82,96,130,1,11,22,116,93,68,138,252,42,4,33,251,223,4,147,175,59,55,51,10,4,34,24,59,64,174,60,55,22,32,4,11,54,60,254,208,176,59,56,51,10,5,36,23,60,65,174,62,55,55,5,10,55,61,254,136,172,0,0,0,0,3,0,88, +0,149,4,121,4,147,0,27,0,55,0,83,0,0,1,21,14,1,35,34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,23,51,22,23,22,51,50,54,19,21,14,1,35,34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,22,23,22,23,22,51,50,54,19,21,14,1,35,34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,23, +51,22,23,22,51,50,54,4,121,75,143,79,90,113,22,11,83,99,49,78,141,74,79,146,82,96,130,1,11,22,116,93,68,138,75,75,143,79,90,113,22,11,77,103,51,79,141,73,78,146,83,53,100,75,10,22,116,93,70,137,74,75,143,79,90,113,22,11,83,99,49,78,141,74,79,146,82,96, +130,1,11,22,116,93,68,138,1,184,176,59,56,51,10,5,36,23,60,65,174,62,55,55,5,10,55,61,3,27,175,59,55,51,10,4,34,24,59,64,174,60,55,22,32,4,11,54,60,254,208,176,59,56,51,10,5,36,23,60,65,174,62,55,55,5,10,55,61,0,0,0,3,0,88,0,192,4,121,4,143,0,3,0,7,0, +36,0,0,1,21,33,53,1,21,33,53,17,30,1,51,50,55,54,55,54,55,54,51,50,22,23,21,46,1,35,34,6,7,6,7,6,35,34,38,39,4,121,251,223,4,33,251,223,74,137,70,93,116,22,10,86,39,50,53,83,146,78,73,141,79,51,103,77,11,22,113,90,79,143,75,2,216,172,172,254,148,172, +172,3,35,63,60,54,11,4,34,9,11,55,60,174,64,59,24,34,4,10,51,55,59,0,2,0,87,0,221,4,121,4,39,0,8,0,17,0,0,0,32,37,53,4,23,50,37,21,0,32,5,21,36,39,34,5,53,3,49,254,112,254,182,1,90,184,185,1,86,253,40,1,144,1,73,254,167,184,185,254,169,2,217,156,178, +156,7,163,178,254,182,156,178,156,7,163,178,0,0,0,2,0,88,0,68,4,122,4,190,0,29,0,59,0,0,37,22,55,54,55,54,55,33,21,35,6,7,6,7,6,35,34,39,38,39,38,39,35,53,33,22,23,22,23,22,19,6,7,6,7,6,7,33,53,51,54,55,54,55,54,51,50,23,22,23,22,23,51,21,33,38,39,38, +39,38,2,105,49,42,43,27,21,4,1,86,225,9,25,27,87,74,82,78,77,82,32,25,9,225,1,87,4,21,26,44,33,58,58,33,44,26,21,4,254,169,225,6,28,22,92,72,83,76,80,77,37,23,11,225,254,170,3,22,27,43,42,223,3,37,39,72,58,94,168,50,58,65,60,51,51,54,71,56,52,168,94, +58,72,39,30,3,64,4,30,39,72,63,89,168,32,76,61,64,51,51,47,78,48,60,168,94,58,72,39,37,0,0,0,2,0,88,1,96,4,122,4,190,0,29,0,33,0,0,1,6,7,6,7,6,7,33,53,51,54,55,54,55,54,51,50,23,22,23,22,23,51,21,33,38,39,38,39,38,1,33,21,33,2,105,58,33,44,26,21,4,254, +169,225,6,28,22,92,72,83,76,80,77,37,23,11,225,254,170,3,22,27,43,42,253,190,4,33,251,223,4,35,4,30,39,72,63,89,168,32,76,61,64,51,51,47,78,48,60,168,94,58,72,39,37,253,228,170,0,255,255,0,88,1,96,4,121,5,25,16,38,0,32,0,0,16,7,8,182,0,2,1,185,255,255, +0,88,255,233,4,121,5,25,16,38,0,32,0,0,16,39,8,182,0,2,1,185,16,39,8,182,0,2,1,185,16,7,8,182,0,1,253,186,255,255,0,88,255,236,4,121,5,25,16,39,8,182,1,148,253,189,16,38,0,32,0,0,16,7,8,182,254,111,1,185,255,255,0,87,255,236,4,122,5,25,16,39,8,182,1, +148,1,185,16,38,0,32,0,0,16,7,8,182,254,110,253,189,0,4,0,74,1,46,4,135,3,213,0,3,0,7,0,11,0,15,0,0,19,51,17,35,17,51,17,35,5,21,33,53,1,21,33,53,74,236,236,236,236,4,61,252,251,3,5,252,251,2,62,254,240,2,167,254,240,185,172,172,1,150,170,170,0,4,0,74, +1,46,4,135,3,213,0,3,0,7,0,11,0,15,0,0,1,17,35,17,19,17,35,17,1,33,21,33,17,33,21,33,4,135,236,236,236,252,175,3,5,252,251,3,5,252,251,2,62,254,240,1,16,1,151,254,240,1,16,254,55,172,2,66,170,0,0,0,0,2,0,88,1,96,4,121,3,162,0,9,0,27,0,0,1,6,21,20,23, +51,54,53,38,39,23,33,21,33,53,33,38,53,52,55,33,53,33,21,33,22,21,20,2,37,52,51,145,52,1,52,141,1,56,251,223,1,62,25,27,254,192,4,33,254,201,26,2,250,48,73,71,48,48,71,71,50,240,170,170,63,56,62,59,168,168,26,95,56,0,0,0,4,0,88,1,96,4,121,6,21,0,3,0, +7,0,17,0,32,0,0,19,33,21,33,17,33,21,33,1,34,6,21,20,22,50,54,52,38,39,50,22,23,30,1,21,20,6,35,34,38,53,52,54,88,4,33,251,223,4,33,251,223,2,17,73,100,100,146,100,101,72,58,108,39,42,42,169,122,123,164,168,2,12,172,2,66,170,2,172,98,70,69,96,96,139, +98,113,43,40,40,100,58,115,161,158,118,118,163,0,3,0,88,1,96,4,121,5,75,0,3,0,7,0,17,0,0,19,33,21,33,17,33,21,33,1,50,23,21,38,39,6,7,53,54,88,4,33,251,223,4,33,251,223,2,18,230,203,215,218,216,220,210,2,12,172,2,66,170,2,83,151,178,151,9,2,158,178,151, +0,0,0,3,0,88,1,96,4,121,6,68,0,3,0,7,0,14,0,0,19,33,21,33,17,33,21,33,55,19,51,19,35,11,1,88,4,33,251,223,4,33,251,223,214,234,162,233,143,171,166,2,12,172,2,66,170,242,2,90,253,166,1,170,254,86,0,3,0,88,1,96,4,121,6,68,0,3,0,7,0,14,0,0,19,33,21,33,17, +33,21,33,19,51,27,1,51,3,35,88,4,33,251,223,4,33,251,223,214,149,166,171,143,233,162,2,12,172,2,66,170,3,76,254,86,1,170,253,166,0,0,3,0,88,1,96,4,121,6,165,0,3,0,7,0,17,0,0,19,33,21,33,17,33,21,33,19,33,27,1,33,7,19,39,7,19,88,4,33,251,223,4,33,251, +223,176,1,13,84,85,1,12,218,85,220,219,84,2,12,172,2,66,170,2,173,1,0,255,0,158,255,0,159,159,1,0,0,4,0,88,1,96,4,121,6,176,0,3,0,7,0,10,0,14,0,0,19,33,21,33,17,33,21,33,1,3,33,3,51,1,33,88,4,33,251,223,4,33,251,223,2,16,150,1,45,201,101,1,4,253,147, +2,12,172,2,66,170,3,21,254,122,2,40,253,105,0,0,0,0,7,0,69,1,96,4,140,6,29,0,3,0,7,0,27,0,48,0,55,0,71,0,79,0,0,19,33,21,33,17,33,21,33,1,21,35,34,6,29,1,51,21,35,17,35,17,35,53,51,53,52,54,51,3,21,33,30,1,51,50,54,55,21,14,1,35,34,38,53,52,54,51,50, +22,7,46,1,35,34,6,7,39,53,51,17,35,53,14,1,35,34,38,52,54,51,50,22,6,20,22,50,54,52,38,34,88,4,33,251,223,4,33,251,223,4,52,64,35,28,109,109,67,63,63,63,68,237,254,208,4,74,66,38,71,36,36,75,38,97,113,107,91,81,95,66,1,59,49,56,66,5,199,67,67,21,63,45, +73,92,92,73,45,63,204,60,105,60,60,105,2,12,172,2,66,170,3,36,55,29,37,36,51,254,160,1,96,51,28,68,61,254,170,32,68,72,19,18,62,15,16,112,96,99,116,105,70,54,65,63,57,105,218,253,208,61,36,35,116,190,117,35,103,147,83,83,147,83,0,3,0,88,1,96,4,121,6, +20,0,3,0,7,0,42,0,0,19,33,21,33,17,33,21,33,1,62,1,51,50,22,21,17,35,17,52,38,35,34,6,21,17,35,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,22,88,4,33,251,223,4,33,251,223,2,46,34,93,63,84,92,89,56,56,69,81,89,55,58,68,81,89,89,31,85,59,59,82,2,12,172, +2,66,170,2,165,61,58,120,111,254,181,1,72,79,77,93,81,254,202,1,72,80,76,94,80,254,202,2,37,85,50,48,61,0,0,0,4,0,88,1,96,4,121,6,218,0,3,0,7,0,11,0,44,0,0,19,33,21,33,17,33,21,33,1,51,21,35,55,35,53,52,54,63,1,62,1,53,52,38,35,34,6,7,53,62,1,51,50,22, +21,20,6,15,1,14,1,7,14,1,21,88,4,33,251,223,4,33,251,223,1,195,102,102,99,96,28,45,45,29,25,65,54,40,89,49,47,97,51,92,112,36,45,44,24,19,4,3,3,2,12,172,2,66,170,1,105,127,200,78,50,65,43,44,27,47,24,45,55,35,33,94,28,28,97,79,38,69,43,43,23,27,13,10, +30,26,0,1,0,88,0,37,4,121,4,221,0,19,0,60,64,32,13,12,10,3,2,4,0,160,6,12,14,10,160,18,6,16,8,20,18,14,13,12,8,4,3,2,8,9,5,15,0,20,16,212,60,196,50,23,57,49,0,16,212,60,196,50,252,60,196,16,254,60,196,57,17,18,57,48,19,33,19,23,7,51,21,33,7,33,21,33, +3,39,55,35,53,33,55,33,88,2,135,246,125,164,203,254,178,184,2,6,253,121,248,125,164,201,1,74,184,253,254,3,162,1,59,102,213,170,236,172,254,197,104,211,172,236,0,3,0,88,0,192,4,121,4,66,0,3,0,7,0,11,0,0,19,33,21,33,21,33,21,33,17,33,21,33,88,4,33,251, +223,4,33,251,223,4,33,251,223,2,216,172,192,172,3,130,170,0,0,1,0,88,0,10,4,121,4,250,0,27,0,0,37,35,53,33,55,33,53,33,55,33,53,33,55,23,7,51,21,33,7,33,21,33,7,33,21,33,7,39,1,71,239,1,61,88,254,107,1,229,88,253,195,2,139,85,141,55,235,254,200,89,1, +145,254,32,90,2,58,253,119,83,141,192,172,192,172,192,170,184,65,119,170,192,172,192,172,182,64,0,0,4,0,88,0,0,4,121,4,238,0,3,0,7,0,11,0,15,0,0,55,33,21,33,17,33,21,33,21,33,21,33,17,33,21,33,88,4,33,251,223,4,33,251,223,4,33,251,223,4,33,251,223,172, +172,3,132,172,192,172,3,130,170,0,0,2,0,88,0,0,4,121,4,63,0,6,0,10,0,40,64,22,6,5,3,2,0,5,1,229,4,228,7,160,8,6,7,4,0,40,9,2,39,11,16,252,60,236,50,50,57,49,0,47,236,244,236,23,57,48,1,21,1,53,1,21,5,1,21,33,53,4,121,251,223,4,33,252,223,3,33,251,223, +1,182,182,1,76,168,1,75,184,231,254,10,170,170,0,0,0,0,2,0,88,0,0,4,121,4,63,0,6,0,10,0,40,64,22,5,4,2,1,0,5,6,229,3,228,7,160,9,1,8,4,40,7,2,0,39,11,16,252,60,60,236,50,57,49,0,47,236,244,236,23,57,48,19,45,1,53,1,21,1,21,33,21,33,88,3,35,252,221,4, +33,251,223,4,33,251,223,1,182,234,231,184,254,181,168,254,180,86,170,0,3,0,86,255,84,4,119,4,159,0,3,0,10,0,14,0,0,51,33,21,33,1,21,1,53,1,21,5,1,21,33,53,86,4,33,251,223,4,33,251,223,4,33,252,223,3,33,251,223,172,2,194,182,1,76,168,1,75,184,231,254, +10,170,170,0,0,0,0,3,0,86,255,84,4,119,4,159,0,3,0,10,0,14,0,0,51,33,21,33,17,45,1,53,1,21,1,5,21,33,53,86,4,33,251,223,3,33,252,223,4,33,251,223,4,33,251,223,172,2,194,234,231,184,254,181,168,254,180,86,170,170,0,2,0,86,254,181,4,119,4,159,0,19,0,26, +0,0,5,35,53,33,55,33,53,33,55,23,7,51,21,33,7,33,21,33,7,39,1,21,1,53,1,21,5,1,32,202,1,112,91,254,53,2,109,154,123,42,201,254,149,91,1,198,253,148,153,121,3,126,251,223,4,33,252,223,172,172,96,170,161,117,44,170,96,172,159,118,2,235,182,1,76,168,1,75, +184,231,0,2,0,86,254,181,4,119,4,159,0,19,0,26,0,0,5,35,53,33,55,33,53,33,55,23,7,51,21,33,7,33,21,33,7,39,3,45,1,53,1,21,1,1,32,202,1,112,91,254,53,2,109,154,123,42,201,254,149,91,1,198,253,148,153,121,163,3,33,252,223,4,33,251,223,172,172,96,170,161, +117,44,170,96,172,159,118,2,235,234,231,184,254,181,168,254,180,0,0,0,0,1,0,87,0,0,4,121,5,4,0,27,0,0,1,38,37,53,4,55,19,23,3,54,55,21,6,15,1,22,5,21,36,7,3,39,19,6,7,53,54,55,2,52,189,254,224,1,91,216,194,154,130,122,154,216,162,98,190,1,31,254,165, +216,193,154,129,124,152,219,160,2,219,18,136,178,170,8,1,127,77,254,254,41,73,178,103,35,194,18,136,178,170,8,254,129,77,1,2,40,74,178,104,35,0,2,0,88,255,227,4,121,5,32,0,15,0,18,0,0,1,37,53,37,19,23,7,37,21,5,3,5,21,37,3,39,19,5,23,1,225,254,119,2, +50,114,153,75,1,47,254,146,100,1,210,253,254,116,153,228,254,217,233,1,148,155,166,222,1,109,48,241,120,182,138,254,187,174,183,203,254,139,48,2,221,111,86,0,0,2,0,88,255,227,4,121,5,32,0,15,0,18,0,0,1,5,21,5,3,39,55,5,53,37,19,37,53,5,19,23,3,37,39, +2,240,1,137,253,206,114,153,75,254,209,1,110,100,254,46,2,2,116,153,228,1,39,233,3,111,155,166,222,254,147,48,241,120,182,138,1,69,174,183,203,1,117,48,253,35,111,86,0,0,2,0,88,255,13,4,121,5,8,0,2,0,26,0,0,1,5,23,3,33,53,33,19,37,53,37,19,23,7,37,21, +5,7,5,21,37,7,33,21,33,7,39,2,88,255,0,211,199,254,244,1,67,95,254,94,2,63,115,161,77,1,27,254,164,78,1,170,254,35,78,2,43,253,158,80,162,2,234,74,62,253,158,170,1,31,131,168,180,1,96,53,237,89,184,100,241,124,182,150,236,170,243,53,0,2,0,88,255,13,4, +121,5,8,0,23,0,26,0,0,1,5,21,5,7,33,21,33,7,39,55,35,53,51,55,5,53,37,55,37,53,5,19,23,3,55,39,2,224,1,153,253,203,78,2,131,253,69,79,162,62,179,235,58,254,219,1,102,76,254,78,1,230,116,161,208,248,206,3,116,128,168,177,241,170,243,53,190,170,178,92, +182,104,236,125,184,152,1,97,53,253,133,72,60,0,2,0,86,255,212,4,119,4,63,0,28,0,35,0,0,37,21,14,1,35,34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,23,22,23,22,23,22,51,50,54,19,21,1,53,1,21,5,4,119,75,143,79,90,113,22,11,77,103,51,79,141,73,78,146,83,53, +50,39,86,10,22,116,93,70,137,74,251,223,4,33,252,223,245,175,59,55,51,10,4,34,24,59,64,174,60,55,11,9,34,4,11,54,60,1,0,182,1,76,168,1,75,184,231,0,0,0,2,0,86,255,212,4,119,4,63,0,33,0,40,0,0,37,21,6,7,6,35,34,39,38,39,38,39,38,35,34,7,6,7,53,54,55,54, +51,50,23,22,23,22,23,22,51,50,55,54,1,45,1,53,1,21,1,4,119,75,72,71,79,90,113,22,11,77,51,52,51,79,70,71,73,78,73,73,83,53,50,39,86,10,22,116,93,70,68,69,252,41,3,33,252,223,4,33,251,223,245,175,59,27,28,51,10,4,34,12,12,29,30,64,174,60,28,27,11,9,34, +4,11,54,30,30,1,0,234,231,184,254,181,168,254,180,0,2,0,86,255,13,4,119,5,8,0,43,0,46,0,0,37,34,6,7,53,62,1,51,50,23,55,37,53,37,19,23,7,37,21,5,7,5,21,37,7,22,23,22,51,50,54,55,21,14,1,35,34,39,38,39,38,39,3,39,1,5,23,1,125,81,141,73,78,146,83,21,21, +69,254,94,2,65,115,161,77,1,25,254,167,80,1,169,254,35,66,24,29,116,93,70,137,74,75,143,79,90,113,22,11,32,28,95,162,1,52,254,253,213,79,59,64,174,60,55,2,214,131,168,181,1,95,53,236,88,184,99,242,124,182,150,207,8,15,54,60,63,175,59,55,51,10,4,14,11, +254,223,53,3,169,75,62,0,0,0,0,2,0,86,255,13,4,119,5,8,0,2,0,50,0,0,1,55,39,55,5,21,5,7,22,23,22,23,22,51,50,55,54,55,21,6,7,6,35,34,39,38,39,38,39,3,39,19,6,7,6,7,53,54,55,54,63,1,5,53,37,55,37,53,5,19,23,2,131,244,202,51,1,151,253,205,59,24,76,10,22, +116,93,70,68,69,74,71,76,71,79,90,113,22,11,80,60,103,162,85,31,29,71,73,78,73,53,58,34,254,216,1,103,78,254,75,1,232,116,161,2,89,71,59,152,127,168,177,184,5,31,4,11,54,30,30,63,175,56,30,28,51,10,4,36,13,254,199,53,1,3,7,12,30,64,174,60,28,20,5,106, +93,182,105,234,126,184,153,1,98,53,0,0,2,0,86,255,74,4,119,4,211,0,6,0,13,0,0,51,45,1,53,1,21,9,1,21,1,53,1,21,5,86,3,33,252,223,4,33,251,223,4,33,251,223,4,33,252,223,234,231,184,254,181,168,254,180,3,0,182,1,76,168,1,75,184,231,0,0,0,0,2,0,86,255,74, +4,119,4,211,0,6,0,13,0,0,33,21,1,53,1,21,5,1,45,1,53,1,21,1,4,119,251,223,4,33,252,223,255,0,3,33,252,223,4,33,251,223,182,1,76,168,1,75,184,231,1,96,234,231,184,254,181,168,254,180,0,0,0,3,0,86,254,112,4,119,5,177,0,2,0,30,0,33,0,0,1,5,31,1,5,21,37, +7,5,21,5,3,39,55,7,53,37,19,37,53,5,55,37,53,37,19,23,7,55,21,5,3,37,39,2,132,254,210,252,163,1,130,254,78,25,1,203,253,155,109,162,76,249,1,52,80,254,124,1,181,24,254,51,2,104,110,162,76,245,254,206,250,1,44,250,3,139,87,74,47,113,182,136,78,144,168, +193,254,155,48,248,78,182,90,1,7,112,184,137,79,145,168,193,1,104,50,249,77,184,88,252,207,88,72,0,3,0,86,254,112,4,119,5,177,0,27,0,30,0,33,0,0,1,23,3,5,21,5,7,37,21,5,7,5,21,37,3,39,19,37,53,37,55,5,53,37,55,37,53,5,1,55,7,1,7,55,3,44,162,126,1,39, +254,98,29,1,187,254,10,48,2,38,253,170,124,162,125,254,214,1,162,29,254,65,1,249,48,253,215,2,89,254,255,17,105,1,204,17,102,5,177,50,254,101,92,168,130,96,139,184,145,159,161,182,188,254,106,48,1,152,94,168,131,95,140,182,147,158,160,184,188,252,185, +56,30,2,99,55,30,0,0,1,0,86,255,211,4,119,5,47,0,10,0,0,1,0,5,4,1,21,0,37,53,36,1,4,119,254,185,254,92,1,172,1,63,254,185,253,38,2,222,1,67,4,64,254,152,87,97,254,162,239,1,197,150,166,148,1,199,0,0,1,0,88,255,211,4,121,5,47,0,10,0,0,19,53,0,5,21,4,1, +53,0,37,36,88,1,67,2,222,253,38,254,185,1,63,1,172,254,92,4,64,239,254,57,148,166,150,254,59,239,1,94,97,87,0,0,2,0,86,255,4,4,119,5,177,0,9,0,24,0,0,37,38,37,53,4,23,4,23,21,38,19,0,5,4,1,21,38,37,38,37,53,36,55,36,55,2,164,224,254,146,1,112,222,1,8, +203,177,177,254,221,254,108,1,148,1,35,183,254,228,247,254,169,1,97,237,1,28,183,155,154,54,200,56,131,156,220,252,207,4,239,254,208,79,93,254,222,239,201,151,130,57,166,61,125,150,203,0,0,0,2,0,86,255,4,4,119,5,177,0,9,0,24,0,0,37,4,7,53,54,37,54,37, +21,4,1,53,22,5,22,5,21,4,7,4,7,53,0,37,36,2,41,254,222,177,203,1,8,222,1,112,254,146,253,77,183,1,28,237,1,97,254,169,247,254,228,183,1,35,1,148,254,108,155,200,207,252,220,156,131,56,200,54,3,141,239,203,150,125,61,166,57,130,151,201,239,1,34,93,79, +0,0,0,0,2,0,86,255,142,4,119,5,177,0,27,0,42,0,0,37,21,14,1,35,34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,22,23,22,23,22,51,50,54,19,0,5,4,1,21,38,37,38,37,53,36,55,36,55,4,119,75,143,79,90,113,22,11,77,103,51,79,141,73,78,146,83,53,100,75,10,22,116,93, +70,137,74,254,221,254,108,1,148,1,35,183,254,228,247,254,169,1,97,237,1,28,183,175,175,59,55,51,10,4,34,24,59,64,174,60,55,22,32,4,11,54,60,4,82,254,208,79,93,254,222,239,201,151,130,57,166,61,125,150,203,0,0,0,0,2,0,86,255,142,4,119,5,177,0,27,0,42, +0,0,37,21,14,1,35,34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,22,23,22,23,22,51,50,54,1,53,22,5,22,5,21,4,7,4,7,53,0,37,36,4,119,75,143,79,90,113,22,11,77,103,51,79,141,73,78,146,83,53,100,75,10,22,116,93,70,137,252,41,183,1,28,237,1,97,254,169,247,254, +231,186,1,35,1,148,254,108,175,175,59,55,51,10,4,34,24,59,64,174,60,55,22,32,4,11,54,60,4,82,239,203,150,125,61,166,57,130,148,204,239,1,34,93,79,0,0,2,0,86,255,91,4,119,5,167,0,21,0,26,0,0,1,23,3,54,55,21,6,7,3,22,23,21,38,37,3,39,19,38,39,53,36,55, +3,55,6,7,22,3,52,163,104,155,109,160,181,85,233,193,178,254,214,160,162,166,192,233,1,71,246,99,32,95,101,84,5,167,50,254,170,119,153,239,176,110,254,235,119,212,239,247,157,253,244,50,2,34,79,48,166,66,127,254,188,106,37,21,19,0,0,2,0,86,255,91,4,119, +5,167,0,21,0,26,0,0,5,39,19,6,7,53,54,55,19,38,39,53,22,5,19,23,3,22,23,21,4,7,19,7,54,55,38,1,153,163,104,155,109,160,181,85,233,193,178,1,42,160,162,166,192,233,254,185,246,99,32,95,101,84,165,50,1,86,119,153,239,176,110,1,21,119,212,239,247,157,2, +12,50,253,222,79,48,166,66,127,1,68,106,37,21,19,0,0,0,1,0,88,0,163,4,121,4,95,0,20,0,0,37,33,34,39,38,53,52,55,54,51,33,21,33,34,6,21,20,23,22,51,33,4,121,253,189,201,138,139,139,138,200,2,68,253,188,137,190,95,96,136,2,68,163,139,139,200,198,141,139, +150,192,136,138,94,96,0,0,0,0,1,0,88,0,163,4,121,4,95,0,20,0,0,55,53,33,50,55,54,53,52,38,35,33,53,33,50,23,22,21,20,7,6,35,88,2,68,136,96,95,190,137,253,188,2,68,200,138,139,139,138,201,163,150,96,94,138,136,192,150,139,141,198,200,139,139,0,0,2,0,88, +255,196,4,121,5,62,0,8,0,32,0,0,1,35,34,6,21,20,23,22,23,7,38,39,38,53,52,55,54,59,1,55,23,7,33,21,33,3,33,21,33,34,35,7,39,2,127,74,137,190,95,43,51,48,84,68,139,139,138,200,126,75,161,57,1,19,254,186,221,2,35,253,189,10,10,75,162,3,201,192,136,138, +94,43,24,144,35,69,139,200,198,141,139,223,53,170,150,253,112,150,223,53,0,0,0,2,0,88,255,196,4,121,5,62,0,8,0,32,0,0,1,51,50,54,53,52,39,38,39,55,22,23,22,21,20,7,6,43,1,7,39,55,33,53,33,19,33,53,33,50,51,55,23,2,82,74,137,190,95,43,51,48,84,68,139, +139,138,200,126,75,161,57,254,237,1,70,221,253,221,2,67,10,10,75,162,1,57,192,136,138,94,43,24,144,35,69,139,200,198,141,139,223,53,170,150,2,144,150,223,53,0,0,0,2,0,88,0,0,4,121,5,0,0,3,0,24,0,0,37,21,33,53,37,33,34,39,38,53,52,55,54,51,33,21,33,34, +6,21,20,23,22,51,33,4,121,251,223,4,33,253,189,201,138,139,139,138,200,2,68,253,188,137,190,95,96,136,2,68,170,170,170,154,139,139,200,198,141,139,150,192,136,138,94,96,0,0,0,2,0,88,0,0,4,121,5,0,0,3,0,24,0,0,37,21,33,61,2,33,50,55,54,53,52,38,35,33, +53,33,50,23,22,21,20,7,6,35,4,121,251,223,2,68,136,96,95,190,137,253,188,2,68,200,138,139,139,138,201,170,170,170,154,150,96,94,138,136,192,150,139,141,198,200,139,139,0,0,0,2,0,88,255,44,4,121,5,214,0,29,0,38,0,0,37,33,21,33,7,39,55,35,53,33,55,38,39, +38,53,52,55,54,59,1,55,23,7,51,21,33,3,33,21,33,19,35,34,6,21,20,23,22,23,2,36,2,85,253,114,71,159,54,227,1,27,58,113,89,139,139,138,200,178,71,158,53,226,254,236,220,1,240,253,221,94,127,137,190,95,61,82,170,170,212,53,159,170,172,32,89,139,200,198, +141,139,214,53,161,150,253,112,150,3,38,192,136,136,96,61,23,0,0,0,2,0,88,255,44,4,121,5,214,0,33,0,43,0,0,1,22,23,22,21,20,7,6,43,1,7,33,21,33,7,39,55,35,53,33,55,33,53,33,19,38,35,33,53,33,50,23,55,23,1,51,50,55,54,53,52,39,38,39,3,131,57,50,139,139, +138,201,68,52,2,86,253,113,70,159,53,226,1,27,51,254,178,1,129,219,12,12,253,188,2,68,38,35,73,158,254,188,20,136,96,95,95,24,26,4,199,32,50,141,198,200,139,139,154,170,212,53,159,170,154,150,2,143,1,150,5,219,53,252,57,96,94,138,136,96,24,18,0,0,0,1, +0,88,255,48,4,121,5,0,0,33,0,0,37,21,33,7,39,55,33,53,33,55,35,34,39,38,53,52,55,54,51,33,21,33,34,6,21,20,23,22,51,33,21,33,23,7,4,121,254,24,167,132,82,254,160,1,232,124,134,201,138,139,139,138,200,2,68,253,188,137,190,95,97,135,2,68,254,177,65,81, +170,170,208,106,102,170,154,139,140,199,198,141,139,150,192,136,138,94,96,150,53,101,0,1,0,88,255,48,4,121,5,0,0,34,0,0,37,21,33,7,39,55,33,53,33,55,6,35,33,53,33,50,55,54,53,52,38,35,33,53,33,50,23,22,21,20,7,6,7,23,7,4,121,254,24,167,132,82,254,160, +1,232,124,16,17,253,189,2,68,135,97,95,190,137,253,188,2,68,200,138,139,139,93,122,84,81,170,170,208,106,102,170,155,1,150,96,94,138,136,192,150,139,141,198,199,140,94,30,68,101,0,2,0,131,255,227,4,78,5,4,0,3,0,21,0,0,1,51,21,35,37,17,51,17,20,22,51, +50,54,53,17,51,17,16,6,33,32,38,1,253,212,212,254,134,172,148,166,165,148,172,225,254,252,254,251,225,2,160,226,49,3,21,253,24,244,161,161,244,2,232,252,235,254,216,228,228,0,2,0,131,255,227,4,78,5,4,0,17,0,29,0,0,19,17,51,17,20,22,51,50,54,53,17,51, +17,16,6,33,32,38,1,21,51,21,35,21,35,53,35,53,51,53,131,172,148,166,165,148,172,225,254,252,254,251,225,2,24,170,170,101,170,170,1,239,3,21,253,24,244,161,161,244,2,232,252,235,254,216,228,228,2,68,170,100,172,172,100,170,0,1,0,88,0,119,4,121,4,139,0, +7,0,49,0,176,6,47,176,7,51,177,4,4,237,177,5,4,237,176,2,176,4,16,222,176,3,50,177,0,4,237,177,1,4,237,1,176,0,47,176,7,51,177,3,4,237,177,4,4,237,48,49,19,33,21,33,17,33,21,33,88,4,33,252,137,3,119,251,223,4,139,170,253,64,170,0,0,0,1,0,88,0,119,4,121, +4,139,0,7,0,49,0,176,1,47,176,2,51,177,3,4,237,177,4,4,237,176,5,176,3,16,222,176,6,50,177,0,4,237,177,7,4,237,1,176,4,47,176,5,51,177,0,4,237,177,1,4,237,48,49,1,17,33,53,33,17,33,53,4,121,251,223,3,119,252,137,4,139,251,236,170,2,192,170,0,0,2,0,88, +0,14,4,121,4,244,0,3,0,11,0,72,0,176,2,47,176,3,51,177,0,4,237,177,1,4,237,176,10,176,0,16,222,176,11,50,177,8,4,237,177,9,4,237,176,6,176,8,16,222,176,7,50,177,4,4,237,177,5,4,237,1,176,0,47,176,3,51,176,4,51,176,11,51,177,7,4,237,177,8,4,237,48,49, +55,33,21,33,17,33,21,33,17,33,21,33,88,4,33,251,223,4,33,252,137,3,119,251,223,184,170,4,230,170,253,152,170,0,0,0,0,2,0,88,0,14,4,121,4,244,0,3,0,11,0,74,0,176,1,47,176,2,51,177,0,4,237,177,3,4,237,176,5,176,0,16,222,176,6,50,177,7,4,237,177,8,4,237, +176,9,176,7,16,222,176,10,50,177,4,4,237,177,11,4,237,1,176,8,47,176,9,51,177,0,4,237,177,1,4,237,177,4,4,237,177,5,4,237,48,49,37,21,33,53,1,17,33,53,33,17,33,53,4,121,251,223,4,33,251,223,3,119,252,137,184,170,170,4,60,252,68,170,2,104,170,0,0,0,0, +1,0,94,0,0,4,114,5,4,0,7,0,0,1,17,35,17,33,17,35,17,4,114,170,253,64,170,5,4,250,252,4,90,251,166,5,4,0,0,0,1,0,94,0,0,4,114,5,4,0,7,0,0,51,17,51,17,33,17,51,17,94,170,2,192,170,5,4,251,166,4,90,250,252,0,0,3,0,79,0,105,4,130,4,158,0,25,0,51,0,63,0,0, +0,50,22,23,22,23,22,21,20,7,6,7,14,1,34,38,39,38,39,38,53,52,55,54,55,54,4,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,39,7,51,17,33,21,33,17,35,17,33,53,33,1,250,221,190,79,79,39,39,39,39,79,79,190,221,190,79,79,39,39,39,39,79, +79,1,126,163,71,69,58,59,57,57,59,58,69,71,163,70,70,58,59,57,57,59,58,70,222,140,1,20,254,236,140,254,237,1,19,4,158,80,79,79,95,95,112,109,95,95,79,78,80,80,78,79,95,95,109,112,95,95,79,79,61,30,30,57,59,140,83,80,140,59,57,30,30,30,30,57,59,140,80, +83,140,59,57,30,22,254,235,140,254,238,1,18,140,0,0,0,0,3,0,79,0,105,4,130,4,158,0,25,0,51,0,55,0,0,0,50,22,23,22,23,22,21,20,7,6,7,14,1,34,38,39,38,39,38,53,52,55,54,55,54,4,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,39,19,21, +33,53,1,250,221,190,79,79,39,39,39,39,79,79,190,221,190,79,79,39,39,39,39,79,79,1,126,163,71,69,58,59,57,57,59,58,69,71,163,70,70,58,59,57,57,59,58,70,194,253,77,4,158,80,79,79,95,95,112,109,95,95,79,78,80,80,78,79,95,95,109,112,95,95,79,79,61,30,30, +57,59,140,83,80,140,59,57,30,30,30,30,57,59,140,80,83,140,59,57,30,254,213,140,140,0,3,0,79,0,105,4,130,4,158,0,25,0,51,0,63,0,0,0,50,22,23,22,23,22,21,20,7,6,7,14,1,34,38,39,38,39,38,53,52,55,54,55,54,4,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55, +62,1,53,52,38,39,38,39,5,55,23,55,23,7,23,7,39,7,39,55,1,250,221,190,79,79,39,39,39,39,79,79,190,221,190,79,79,39,39,39,39,79,79,1,126,163,71,69,58,59,57,57,59,58,69,71,163,70,70,58,59,57,57,59,58,70,254,66,99,196,195,99,195,194,99,194,194,99,194,4,158, +80,79,79,95,95,112,109,95,95,79,78,80,80,78,79,95,95,109,112,95,95,79,79,61,30,30,57,59,140,83,80,140,59,57,30,30,30,30,57,59,140,80,83,140,59,57,30,173,99,196,195,99,195,194,99,194,194,99,194,0,0,0,3,0,79,0,105,4,130,4,158,0,25,0,51,0,55,0,0,0,50,22, +23,22,23,22,21,20,7,6,7,14,1,34,38,39,38,39,38,53,52,55,54,55,54,4,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,39,31,1,1,39,1,250,221,190,79,79,39,39,39,39,79,79,190,221,190,79,79,39,39,39,39,79,79,1,126,163,71,69,58,59,57,57,59, +58,69,71,163,70,70,58,59,57,57,59,58,70,44,99,254,24,99,4,158,80,79,79,95,95,112,109,95,95,79,78,80,80,78,79,95,95,109,112,95,95,79,79,61,30,30,57,59,140,83,80,140,59,57,30,30,30,30,57,59,140,80,83,140,59,57,30,75,99,254,24,99,0,0,3,0,79,0,105,4,130, +4,158,0,3,0,29,0,55,0,0,1,51,17,35,18,50,22,23,22,23,22,21,20,7,6,7,14,1,34,38,39,38,39,38,53,52,55,54,55,54,4,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,39,1,233,252,252,17,221,190,79,79,39,39,39,39,79,79,190,221,190,79,79,39, +39,39,39,79,79,1,126,163,71,69,58,59,57,57,59,58,69,71,163,70,70,58,59,57,57,59,58,70,3,16,254,207,2,191,80,79,79,95,95,112,109,95,95,79,78,80,80,78,79,95,95,109,112,95,95,79,79,61,30,30,57,59,140,83,80,140,59,57,30,30,30,30,57,59,140,80,83,140,59,57, +30,0,4,0,79,0,105,4,130,4,158,0,14,0,24,0,50,0,76,0,0,1,50,22,23,30,1,21,20,6,35,34,38,53,52,54,22,34,6,20,22,51,50,54,53,52,2,50,22,23,22,23,22,21,20,7,6,7,14,1,34,38,39,38,39,38,53,52,55,54,55,54,4,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62, +1,53,52,38,39,38,39,2,104,55,98,37,38,39,156,113,113,151,154,167,110,78,76,56,56,79,244,221,190,79,79,39,39,39,39,79,79,190,221,190,79,79,39,39,39,39,79,79,1,126,163,71,69,58,59,57,57,59,58,69,71,163,70,70,58,59,57,57,59,58,70,3,143,41,39,37,96,56,110, +154,151,113,113,156,135,77,112,76,77,55,55,1,228,80,79,79,95,95,112,109,95,95,79,78,80,80,78,79,95,95,109,112,95,95,79,79,61,30,30,57,59,140,83,80,140,59,57,30,30,30,30,57,59,140,80,83,140,59,57,30,0,0,0,7,0,79,0,105,4,130,4,158,0,25,0,33,0,39,0,47,0, +55,0,61,0,69,0,0,0,50,22,23,22,23,22,21,20,7,6,7,14,1,34,38,39,38,39,38,53,52,55,54,55,54,5,17,37,38,39,38,39,38,13,2,54,53,52,3,39,17,54,55,54,55,54,5,17,7,22,23,22,23,22,45,2,6,21,20,19,5,17,6,7,6,7,6,1,250,221,190,79,79,39,39,39,39,79,79,190,221,190, +79,79,39,39,39,39,79,79,1,102,0,255,15,18,58,70,45,1,6,254,236,1,19,28,84,254,49,45,70,58,17,254,158,254,15,17,58,69,46,254,251,1,19,254,236,27,83,0,255,49,46,69,58,18,4,158,80,79,79,95,95,112,109,95,95,79,78,80,80,78,79,95,95,109,112,95,95,79,79,65, +254,207,154,19,19,57,30,19,238,150,150,70,80,81,254,188,153,254,210,7,19,30,57,18,131,1,46,153,18,18,57,30,19,235,150,150,69,81,80,1,68,154,1,49,7,19,30,57,19,0,0,0,4,0,79,0,105,4,130,4,158,0,3,0,7,0,33,0,59,0,0,1,33,21,33,17,33,21,33,18,50,22,23,22, +23,22,21,20,7,6,7,14,1,34,38,39,38,39,38,53,52,55,54,55,54,4,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,39,1,43,2,123,253,133,2,123,253,133,207,221,190,79,79,39,39,39,39,79,79,190,221,190,79,79,39,39,39,39,79,79,1,126,163,71,69, +58,59,57,57,59,58,69,71,163,70,70,58,59,57,57,59,58,70,2,59,103,1,90,102,1,214,80,79,79,95,95,112,109,95,95,79,78,80,80,78,79,95,95,109,112,95,95,79,79,61,30,30,57,59,140,83,80,140,59,57,30,30,30,30,57,59,140,80,83,140,59,57,30,0,0,0,3,0,79,0,105,4,130, +4,158,0,25,0,51,0,55,0,0,0,50,22,23,22,23,22,21,20,7,6,7,14,1,34,38,39,38,39,38,53,52,55,54,55,54,4,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,39,19,33,53,33,1,250,221,190,79,79,39,39,39,39,79,79,190,221,190,79,79,39,39,39,39, +79,79,1,126,163,71,69,58,59,57,57,59,58,69,71,163,70,70,58,59,57,57,59,58,70,50,254,109,1,147,4,158,80,79,79,95,95,112,109,95,95,79,78,80,80,78,79,95,95,109,112,95,95,79,79,61,30,30,57,59,140,83,80,140,59,57,30,30,30,30,57,59,140,80,83,140,59,57,30,254, +73,140,0,0,0,0,3,0,80,0,105,4,131,4,156,0,3,0,7,0,19,0,0,37,17,33,17,3,33,17,33,1,51,17,33,21,33,17,35,17,33,53,33,3,244,252,232,140,4,51,251,205,1,210,140,1,56,254,200,140,254,201,1,55,245,3,27,252,229,3,167,251,205,3,152,254,199,140,254,202,1,54,140, +0,0,0,3,0,80,0,105,4,131,4,156,0,3,0,7,0,11,0,0,37,17,33,17,3,33,17,33,1,21,33,53,3,244,252,232,140,4,51,251,205,3,114,253,77,245,3,27,252,229,3,167,251,205,2,95,140,140,0,3,0,80,0,105,4,131,4,156,0,3,0,7,0,19,0,0,37,17,33,17,3,33,17,33,19,55,9,1,23, +9,1,7,9,1,39,1,3,244,252,232,140,4,51,251,205,172,99,1,11,1,12,99,254,244,1,8,99,254,248,254,246,99,1,10,245,3,27,252,229,3,167,251,205,3,35,99,254,245,1,12,99,254,244,254,248,99,1,8,254,247,99,1,9,0,0,3,0,80,0,105,4,131,4,156,0,3,0,7,0,11,0,0,1,51,17, +35,5,17,33,17,3,33,17,33,1,233,252,252,2,11,252,232,140,4,51,251,205,3,16,254,207,234,3,27,252,229,3,167,251,205,0,1,0,88,0,0,4,121,5,4,0,7,0,0,1,17,33,21,33,17,35,17,1,0,3,121,252,135,168,5,4,253,211,170,253,211,5,4,0,0,0,1,0,88,0,0,4,121,5,4,0,7,0, +0,33,17,33,53,33,17,51,17,3,209,252,135,3,121,168,2,45,170,2,45,250,252,0,1,0,88,0,0,4,121,5,4,0,7,0,0,33,17,33,53,33,21,33,17,2,21,254,67,4,33,254,68,4,90,170,170,251,166,0,1,0,88,0,0,4,121,5,4,0,7,0,0,1,3,33,21,33,53,33,19,2,189,1,1,189,251,223,1,188, +1,5,4,251,166,170,170,4,90,0,2,0,88,0,141,4,121,4,119,0,2,0,6,0,0,9,1,5,23,1,53,1,3,209,253,86,2,170,168,251,223,4,33,3,130,254,255,254,246,1,162,166,1,162,0,0,0,0,2,0,88,0,141,4,121,4,119,0,3,0,6,0,0,19,1,21,1,55,37,1,88,4,33,251,223,168,2,170,253,86, +4,119,254,94,166,254,94,246,254,1,1,0,3,0,88,0,0,4,121,4,63,0,3,0,6,0,10,0,0,37,21,33,53,1,13,1,23,1,53,1,4,121,251,223,3,121,253,135,2,121,168,251,223,4,33,170,170,170,2,173,183,185,231,1,76,168,1,75,0,0,0,0,3,0,88,0,0,4,121,4,63,0,3,0,7,0,10,0,0,55, +33,21,33,17,1,21,1,55,45,1,88,4,33,251,223,4,33,251,223,168,2,123,253,133,170,170,4,63,254,181,168,254,180,231,185,183,0,0,2,0,28,1,103,4,181,3,162,0,13,0,21,0,0,19,55,33,54,55,54,50,22,20,6,34,39,38,39,36,38,34,6,20,22,50,54,28,1,2,105,19,49,91,235, +165,162,242,83,52,19,1,154,79,115,80,79,116,79,2,46,168,68,47,89,167,242,162,82,51,66,142,80,81,113,79,79,0,0,0,1,0,131,254,76,4,78,6,11,0,17,0,0,1,17,35,17,52,38,35,34,6,21,17,35,17,16,54,33,32,22,4,78,172,148,166,165,148,172,225,1,4,1,5,225,3,255,250, +77,5,134,244,161,161,244,250,122,5,179,1,40,228,228,0,1,0,131,254,47,4,78,5,238,0,17,0,0,55,17,51,17,20,22,51,50,54,53,17,51,17,16,6,33,32,38,131,172,148,166,165,148,172,225,254,252,254,251,225,59,5,179,250,122,244,161,161,244,5,134,250,77,254,216,228, +228,0,0,0,2,0,105,0,130,4,103,4,128,0,3,0,7,0,0,9,7,1,89,1,16,1,14,254,240,254,2,1,254,2,0,254,2,2,130,254,240,1,14,1,16,254,242,1,254,254,0,254,2,0,0,0,1,1,233,2,47,2,229,3,96,0,3,0,21,185,0,2,1,1,181,0,4,1,29,0,4,16,212,236,49,0,16,212,236,48,1,51, +17,35,1,233,252,252,3,96,254,207,0,0,1,1,8,1,155,3,201,4,55,0,9,0,0,1,33,19,23,33,7,23,39,7,19,1,9,1,12,84,83,1,12,217,84,218,218,83,3,56,0,255,255,158,255,158,158,0,255,0,2,0,88,1,96,4,121,3,195,0,3,0,31,0,0,1,21,33,53,17,30,1,51,50,55,54,55,62,1,51, +50,22,23,21,46,1,35,34,6,7,6,7,6,35,34,38,39,4,121,251,223,74,137,70,93,116,22,10,75,100,53,83,146,78,73,141,79,51,103,77,11,22,113,90,79,143,75,2,12,172,172,1,183,63,60,54,11,4,32,22,55,60,174,64,59,24,34,4,10,51,55,59,0,0,1,255,248,0,0,4,214,5,4,0, +10,0,0,33,16,1,51,0,19,18,1,51,0,17,2,20,253,228,240,1,113,15,20,1,106,240,253,228,3,125,1,135,254,216,254,212,1,43,1,41,254,121,252,131,0,0,1,255,248,0,0,4,214,5,4,0,10,0,0,1,16,1,35,0,3,2,1,35,0,17,2,186,2,28,240,254,143,15,20,254,150,240,2,28,5,4, +252,131,254,121,1,40,1,44,254,213,254,215,1,135,3,125,0,0,0,0,2,0,90,255,250,4,119,5,10,0,17,0,35,0,0,1,33,34,6,21,20,22,51,33,21,33,34,38,53,52,54,51,33,17,33,32,0,17,16,0,41,1,21,33,34,0,21,20,0,51,33,4,119,254,107,58,80,80,58,1,149,254,106,128,179, +178,129,1,150,254,107,254,241,254,135,1,119,1,15,1,151,254,106,200,254,235,1,21,201,1,149,3,12,81,57,58,80,170,178,130,128,180,252,68,1,123,1,13,1,12,1,124,170,254,232,198,200,254,234,0,2,0,90,255,250,4,119,5,10,0,17,0,35,0,0,19,33,50,54,53,52,38,35, +33,53,33,50,22,21,20,6,35,33,17,33,32,0,17,16,0,41,1,53,33,50,0,53,52,0,35,33,90,1,149,58,80,80,58,254,107,1,150,128,179,178,129,254,106,1,149,1,15,1,121,254,137,254,241,254,105,1,150,200,1,21,254,235,201,254,107,1,248,81,57,58,80,170,178,130,128,180, +3,188,254,133,254,243,254,244,254,132,170,1,24,198,200,1,22,0,0,3,0,88,254,65,4,121,6,21,0,6,0,13,0,17,0,0,55,53,1,21,1,53,37,19,21,1,53,1,21,5,1,21,33,53,88,4,33,251,223,3,35,254,251,223,4,33,252,223,3,33,251,223,202,182,254,180,168,254,181,184,231, +3,172,182,1,76,168,1,75,184,231,254,10,170,170,0,0,0,0,3,0,88,254,65,4,121,6,21,0,6,0,13,0,17,0,0,37,13,1,21,1,53,9,1,45,1,53,1,21,1,21,33,21,33,4,121,252,221,3,35,251,223,4,33,251,223,3,33,252,223,4,33,251,223,4,33,251,223,202,234,231,184,1,75,168,1, +76,2,12,234,231,184,254,181,168,254,180,86,170,0,0,0,0,2,0,86,0,0,4,119,4,63,0,6,0,10,0,0,1,13,1,21,1,53,1,53,33,53,33,4,119,252,223,3,33,251,223,4,33,251,223,4,33,2,137,234,231,184,1,75,168,1,76,86,170,0,0,0,0,2,0,88,0,0,4,121,4,63,0,6,0,10,0,0,19,53, +1,21,1,53,37,1,53,33,21,88,4,33,251,223,3,35,252,221,4,33,2,137,182,254,180,168,254,181,184,231,1,246,170,170,0,2,0,86,255,4,4,119,5,177,0,9,0,24,0,0,1,36,55,21,6,5,6,5,53,36,1,21,38,37,38,37,53,36,55,36,55,21,0,5,4,2,164,1,34,177,203,254,248,222,254, +144,1,110,2,179,183,254,228,237,254,159,1,87,247,1,28,183,254,221,254,108,1,148,4,26,200,207,252,220,156,131,56,200,54,252,115,239,203,150,125,61,166,57,130,151,201,239,254,222,93,79,0,0,0,2,0,86,255,4,4,119,5,177,0,9,0,24,0,0,1,22,5,21,36,39,36,39,53, +22,3,0,37,36,1,53,22,5,22,5,21,4,7,4,7,2,41,224,1,110,254,144,222,254,248,203,177,177,1,35,1,148,254,108,254,221,183,1,28,247,1,87,254,159,237,254,228,183,4,26,154,54,200,56,131,156,220,252,207,251,17,1,48,79,93,1,34,239,201,151,130,57,166,61,125,150, +203,0,0,2,0,86,254,140,4,119,6,41,0,37,0,42,0,0,1,23,7,54,55,21,6,7,3,22,23,21,38,39,7,23,4,23,21,38,37,38,39,3,39,19,38,39,53,22,23,55,38,37,53,36,63,1,3,55,6,7,22,3,100,162,77,106,84,129,152,86,202,165,169,254,51,7,1,8,203,177,254,222,31,33,179,162, +186,163,208,247,182,51,210,254,242,1,97,237,52,109,34,99,106,88,6,41,51,245,83,93,239,135,91,254,238,101,165,239,185,143,161,4,156,220,252,207,200,21,20,253,200,51,2,78,64,30,200,37,72,163,90,45,166,61,125,29,254,164,107,36,21,20,0,0,0,2,0,86,254,140, +4,119,6,41,0,36,0,40,0,0,1,23,3,22,23,21,4,15,1,54,37,21,4,15,1,3,39,19,6,7,53,54,63,1,6,7,53,54,37,55,36,39,53,22,5,22,31,1,7,55,38,3,37,162,165,154,187,255,0,203,68,209,1,62,254,146,224,22,161,162,87,119,90,140,169,78,231,156,204,1,2,40,254,229,219, +183,1,28,43,47,109,5,34,15,6,41,51,253,243,51,32,166,43,83,216,105,48,200,54,154,15,254,0,51,1,22,104,105,252,152,121,247,135,172,239,203,106,127,101,229,239,203,150,23,20,220,14,8,3,0,0,0,0,2,0,88,255,91,4,121,5,167,0,15,0,19,0,0,1,23,7,51,21,33,1,33, +21,33,3,39,55,35,17,33,9,1,33,17,3,80,158,89,228,254,216,254,230,2,66,253,122,114,158,89,228,2,134,254,162,1,26,254,104,5,167,63,221,170,253,64,170,254,228,63,221,4,20,252,150,2,192,253,64,0,0,0,0,2,0,88,255,91,4,121,5,167,0,15,0,19,0,0,1,23,7,51,17, +33,3,39,55,35,53,33,1,33,53,33,23,1,33,17,3,80,158,89,228,253,122,114,158,89,228,1,40,1,26,253,190,2,134,115,254,230,1,152,5,167,63,221,251,236,254,228,63,221,170,2,192,170,170,253,64,2,192,0,0,1,0,88,255,62,4,121,4,244,0,20,0,0,19,33,21,33,17,33,21, +33,23,7,33,21,33,7,39,55,33,53,33,55,33,88,4,33,252,137,3,119,254,210,32,82,1,96,254,24,167,132,82,254,160,1,232,103,253,177,4,244,170,253,152,170,26,102,170,208,106,102,170,128,0,0,0,1,0,88,255,62,4,121,4,244,0,20,0,0,37,21,33,7,39,55,33,53,33,55,33, +53,33,17,33,53,33,17,33,23,7,4,121,254,24,167,132,82,254,160,1,232,103,253,177,3,119,252,137,4,33,254,210,32,82,184,170,208,106,102,170,128,170,2,104,170,252,68,26,102,0,0,0,1,0,86,254,237,4,119,4,63,0,37,0,0,37,38,39,38,35,34,6,7,53,62,1,51,50,22,23, +55,37,53,1,21,13,1,21,37,7,22,51,50,54,55,21,14,1,35,34,39,3,39,2,22,29,23,52,51,79,141,73,78,146,83,58,90,29,48,253,236,4,33,252,223,3,33,254,120,50,88,73,70,137,74,75,143,79,81,100,62,136,51,11,5,12,59,64,174,60,55,22,12,210,167,168,1,75,184,231,234, +182,123,223,34,60,63,175,59,55,41,254,240,31,0,0,1,0,86,254,237,4,119,4,63,0,38,0,0,19,45,1,53,1,21,5,23,3,22,51,50,54,55,21,14,1,35,34,39,3,39,19,38,39,38,35,34,6,7,53,62,1,51,50,22,23,55,5,86,3,33,252,223,4,33,254,63,69,62,88,73,70,137,74,75,143,79, +81,100,62,136,67,29,23,52,51,79,141,73,78,146,83,58,90,29,48,253,236,1,182,234,231,184,254,181,168,141,16,254,237,34,60,63,175,59,55,41,254,240,31,1,39,11,5,12,59,64,174,60,55,22,12,212,167,0,0,0,0,2,0,86,254,75,4,119,5,177,0,31,0,46,0,0,5,38,39,38,35, +34,6,7,53,62,1,51,50,23,22,23,19,23,3,22,51,50,54,55,21,14,1,35,34,39,3,39,1,0,5,4,1,21,38,37,38,37,53,36,55,36,55,2,22,29,23,52,51,79,141,73,78,146,83,54,49,45,29,78,136,83,88,73,70,137,74,75,143,79,81,100,83,136,2,185,254,221,254,108,1,148,1,35,183, +254,228,247,254,169,1,97,237,1,28,183,19,11,5,12,59,64,174,60,55,11,11,12,1,87,31,254,145,34,60,63,175,59,55,41,254,148,31,6,88,254,208,79,93,254,222,239,201,151,130,57,166,61,125,150,203,0,0,0,0,2,0,86,254,75,4,119,5,177,0,31,0,46,0,0,5,38,39,38,35, +34,6,7,53,62,1,51,50,23,22,23,19,23,3,22,51,50,54,55,21,14,1,35,34,39,3,39,1,53,22,5,22,5,21,4,7,4,7,53,0,37,36,2,22,29,23,52,51,79,141,73,78,146,83,54,49,45,29,78,136,83,88,73,70,137,74,75,143,79,81,100,83,136,254,152,183,1,28,237,1,97,254,169,247,254, +231,186,1,35,1,148,254,108,19,11,5,12,59,64,174,60,55,11,11,12,1,87,31,254,145,34,60,63,175,59,55,41,254,148,31,6,88,239,203,150,125,61,166,57,130,148,204,239,1,34,93,79,0,0,255,255,0,80,1,234,4,127,3,27,16,7,7,47,0,0,1,234,0,0,255,255,0,73,0,98,4,138, +4,163,16,6,8,33,0,0,0,1,0,114,1,76,4,82,3,140,0,7,0,0,1,17,1,53,5,17,1,21,2,162,253,208,1,176,2,48,2,122,254,210,1,74,194,250,1,46,254,182,194,0,0,2,0,146,0,0,4,63,4,196,0,4,0,9,0,0,51,17,9,1,17,37,33,17,9,1,146,1,214,1,214,252,206,2,184,254,164,254, +164,2,135,2,61,253,195,253,121,122,1,213,1,171,254,85,0,0,0,1,0,146,3,63,4,62,5,248,0,5,0,0,9,1,35,9,1,35,2,104,1,214,163,254,205,254,205,163,5,248,253,71,1,199,254,57,0,0,0,1,0,146,254,242,4,62,1,172,0,5,0,0,9,1,51,9,1,51,2,104,254,42,163,1,51,1,51, +163,254,242,2,186,254,56,1,200,0,0,0,2,0,146,0,0,4,62,3,142,0,3,0,9,0,0,19,33,21,33,5,1,35,9,1,35,156,3,153,252,103,1,204,1,214,163,254,205,254,205,163,3,142,114,99,253,71,1,199,254,57,0,0,3,0,146,0,0,4,62,4,136,0,3,0,7,0,13,0,0,19,33,21,33,21,33,21, +33,5,1,35,9,1,35,156,3,153,252,103,3,153,252,103,1,204,1,214,163,254,205,254,205,163,4,136,114,136,114,99,253,71,1,199,254,57,0,0,1,1,207,254,242,3,119,6,20,0,5,0,0,1,33,21,35,17,35,1,207,1,168,240,184,6,20,143,249,109,0,0,1,1,90,254,242,3,2,6,20,0,5, +0,0,1,17,35,17,35,53,3,2,184,240,6,20,248,222,6,147,143,0,0,1,1,207,254,242,3,119,6,20,0,5,0,0,1,17,51,17,51,21,1,207,184,240,254,242,7,34,249,109,143,0,0,1,1,90,254,242,3,2,6,20,0,5,0,0,1,33,53,51,17,51,3,2,254,88,240,184,254,242,143,6,147,0,0,2,2,37, +0,150,4,175,3,67,0,3,0,7,0,0,1,33,21,33,7,51,17,35,2,242,1,189,254,67,205,114,114,3,67,114,91,254,32,0,0,2,0,13,0,150,2,151,3,67,0,3,0,7,0,0,19,33,21,33,5,51,17,35,13,1,189,254,67,2,24,114,114,3,67,114,91,254,32,0,0,2,2,37,2,209,4,175,5,126,0,3,0,7,0, +0,1,33,21,33,3,51,17,35,2,242,1,189,254,67,205,114,114,3,67,114,2,173,254,32,0,2,0,13,2,209,2,151,5,126,0,3,0,7,0,0,19,33,21,33,1,51,17,35,13,1,189,254,67,2,24,114,114,3,67,114,2,173,254,32,0,1,0,88,1,115,4,121,3,94,0,5,0,0,1,21,33,17,35,17,4,121,252, +135,168,3,94,172,254,193,1,235,0,2,0,97,1,2,4,112,5,18,0,7,0,15,0,0,19,36,5,2,19,4,37,18,1,18,3,4,37,2,19,36,231,1,129,1,129,137,137,254,127,254,127,137,254,241,184,184,2,7,2,8,184,184,253,248,1,138,137,137,1,128,1,130,138,138,254,126,253,248,1,244,2, +28,177,177,254,12,253,229,177,0,0,0,255,255,0,6,1,176,4,203,4,24,16,6,10,55,0,156,0,2,0,6,1,176,4,203,4,24,0,7,0,15,0,0,19,16,37,54,32,23,4,17,37,33,38,39,38,34,7,6,6,1,49,152,1,49,153,1,50,251,192,3,187,42,192,122,244,122,192,1,176,1,96,176,88,88,176, +254,160,114,197,111,71,71,110,0,0,2,0,184,1,89,4,24,4,24,0,8,0,13,0,0,0,32,23,22,23,9,1,54,55,4,34,7,9,1,1,210,1,44,155,74,53,254,80,254,80,53,74,1,173,248,133,1,2,1,0,4,24,88,42,55,253,250,2,6,55,42,35,76,254,200,1,56,0,2,0,166,0,229,4,21,4,80,0,7,0, +25,0,0,0,34,6,20,22,50,54,52,3,50,23,30,1,21,20,6,35,34,39,7,39,55,38,53,52,54,3,4,196,138,135,199,140,238,158,105,53,54,216,157,127,93,204,81,205,66,214,3,201,137,199,135,137,195,1,18,111,51,133,78,152,214,69,204,81,204,92,124,157,216,0,0,0,6,0,71,0, +233,4,138,5,43,0,3,0,45,0,55,0,65,0,74,0,84,0,0,1,51,53,35,17,21,20,6,34,38,53,52,54,59,1,53,35,34,38,52,54,50,22,29,1,51,53,52,54,50,22,20,6,43,1,21,51,50,22,21,20,6,34,38,61,1,1,53,52,38,35,34,6,20,22,51,19,35,34,6,21,20,22,50,54,53,1,51,50,54,52,38, +34,6,21,17,21,20,22,50,54,53,52,38,35,2,1,207,207,130,183,129,129,89,120,120,89,129,129,183,130,207,130,184,128,128,90,120,120,90,128,128,184,130,254,201,69,49,47,69,69,48,117,117,48,69,69,96,69,1,159,118,47,69,68,97,69,69,97,68,69,47,2,162,208,254,200, +119,90,128,129,92,90,130,208,130,182,129,128,90,119,119,90,128,129,182,130,208,130,90,92,129,128,90,119,1,160,117,48,69,69,96,69,254,96,69,47,49,69,69,48,2,21,69,96,69,69,48,253,235,117,48,69,69,49,47,69,0,0,1,0,88,1,115,4,121,3,94,0,5,0,0,1,33,17,51, +17,33,4,121,251,223,168,3,121,1,115,1,235,254,193,0,0,0,0,1,1,43,2,209,3,181,5,126,0,5,0,0,1,33,17,35,17,33,3,181,253,232,114,2,138,5,12,253,197,2,173,0,0,0,0,1,1,28,2,209,3,166,5,126,0,5,0,0,1,53,33,17,35,17,1,28,2,138,114,5,12,114,253,83,2,59,0,1,1, +43,255,142,3,181,2,59,0,5,0,0,33,21,33,17,51,17,3,181,253,118,114,114,2,173,253,197,0,0,0,1,1,28,255,142,3,166,2,59,0,5,0,0,41,1,17,51,17,33,1,28,2,24,114,253,118,2,59,253,83,0,0,1,2,1,254,0,4,76,7,108,0,25,0,0,1,17,52,55,26,1,51,50,22,21,20,6,35,34, +39,38,39,46,1,35,34,3,2,21,48,17,2,1,3,12,190,202,80,100,64,55,43,28,24,15,6,9,16,104,17,8,254,0,5,8,36,129,2,3,1,188,84,65,54,63,19,16,38,15,72,253,149,254,211,2,250,152,0,0,0,1,0,124,254,26,2,199,7,137,0,25,0,0,1,17,20,7,10,1,35,34,38,53,52,54,51,50, +23,22,23,30,1,51,50,19,18,53,48,17,2,199,3,12,190,202,80,100,64,55,43,28,24,15,6,9,16,104,17,8,7,137,250,245,36,129,253,253,254,68,84,65,54,63,19,16,38,15,72,2,107,1,45,2,5,107,0,0,0,2,0,104,0,233,4,105,4,201,0,7,0,11,0,0,19,33,1,33,21,33,1,35,37,33, +21,33,104,1,92,1,145,1,20,254,114,254,111,226,2,97,1,160,254,96,4,201,252,222,190,3,34,190,190,0,0,5,0,6,1,40,4,203,4,73,0,4,0,10,0,13,0,18,0,21,0,0,9,1,33,17,33,9,1,35,3,19,51,1,23,55,33,35,17,51,27,1,39,7,4,203,254,81,252,234,3,22,1,5,254,211,39,200, +200,39,254,72,131,131,254,111,57,57,200,201,131,131,2,185,254,111,3,33,254,112,1,30,254,225,254,226,2,61,187,187,253,195,1,30,254,226,187,187,0,0,0,5,0,125,1,40,4,84,4,73,0,4,0,8,0,11,0,16,0,19,0,0,1,17,35,3,19,23,33,17,33,5,23,55,33,35,17,51,27,1,39, +7,3,226,108,200,200,222,252,41,3,215,253,145,131,131,254,111,107,107,200,201,131,131,1,154,2,61,254,225,254,226,114,3,33,114,187,187,253,195,1,30,254,226,187,187,0,0,0,43,0,50,1,179,4,159,4,34,0,11,0,23,0,35,0,47,0,59,0,71,0,83,0,95,0,107,0,119,0,131, +0,143,0,155,0,167,0,179,0,191,0,203,0,215,0,227,0,239,0,251,1,7,1,19,1,31,1,43,1,55,1,67,1,79,1,91,1,103,1,115,1,127,1,139,1,151,1,163,1,175,1,187,1,199,1,211,1,227,1,239,1,251,2,7,0,0,19,33,50,21,17,20,35,33,34,53,17,52,23,17,20,51,33,50,53,17,52,35, +33,34,19,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,55,21,20,43,1,34,61,1,52,59,1,50,7,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1, +34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,37,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50, +23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,39,21,20,43,1,34,61,1,52,59,1,50,7,21,20,43,1,34,61,1,52,59,1,50,7,21,20,43,1,34,61,1,52,59,1,50,7,21,20,43,1,34,61,1, +52,59,1,50,7,21,20,43,1,34,61,1,52,59,1,50,7,21,20,43,1,34,61,1,52,59,1,50,7,21,20,43,1,34,61,1,52,59,1,50,7,21,20,43,1,34,61,1,52,59,1,50,39,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43, +1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,7,50,29,1,20,43,1,34,61,1,52,34, +61,1,52,51,19,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,5,34,61,1,52,51,33,50,29,1,20,35,142,3,181,92,92,252,75,92,61,31,3,181,30,30,252,75,31,108,15,31,15,15,31,15,93,15,31,15,15,31,15,138,15,31,16,16,31,15,184,16,31,15,15,31,16, +92,16,30,16,16,30,16,184,16,30,16,16,30,16,92,15,31,16,16,31,15,92,15,31,16,16,31,15,92,15,31,15,15,31,15,93,16,31,15,15,31,16,166,16,105,15,15,105,16,252,197,15,31,15,15,31,15,92,15,31,15,15,31,15,93,16,31,15,15,31,16,91,15,31,15,15,31,15,93,16,31,15, +15,31,16,92,16,31,15,15,31,16,92,15,31,16,16,31,15,92,15,31,16,16,31,15,15,15,31,16,16,31,15,92,15,31,16,16,31,15,92,16,31,15,15,31,16,92,16,31,15,15,31,16,92,16,30,16,16,30,16,92,16,31,15,15,31,16,93,15,31,15,15,31,15,92,15,31,15,15,31,15,15,15,31,15, +15,31,15,92,15,31,15,15,31,15,93,16,31,15,15,31,16,92,16,31,15,15,31,16,92,16,31,15,15,31,16,92,16,31,15,15,31,16,92,16,30,16,16,30,16,92,15,31,16,16,31,15,92,15,31,15,15,31,15,120,16,58,15,15,58,16,16,16,16,102,18,30,15,62,16,31,15,15,31,16,93,16,31, +15,15,31,16,253,89,15,15,1,173,15,15,4,34,92,254,73,92,92,1,183,92,92,254,73,31,31,1,183,31,254,96,30,16,16,30,16,15,31,16,16,31,15,76,31,15,15,31,16,16,31,15,15,31,16,16,31,15,15,31,16,16,31,15,15,31,16,16,31,15,15,31,16,16,31,15,15,31,16,16,31,15,15, +31,16,16,31,15,15,31,16,16,31,15,15,31,16,76,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,77,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15, +31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,15,31,15,75,31,15,15,31,16,16,31,15,15,31,16,16,31,15,15,31,16,16,31,15,15,31,16,16,31,15,15,31,16,16,31,15,15,31,16,16,31,15,15,31,16,16,31,15,15,31,16,16,31,15,15,31,16,16,31,15,15, +31,16,92,15,121,15,15,62,14,15,30,16,254,222,31,16,16,31,15,15,31,16,16,31,15,62,16,31,15,15,31,16,0,0,5,0,6,1,40,4,203,4,73,0,4,0,10,0,13,0,18,0,21,0,0,19,1,33,17,33,9,1,51,19,3,35,41,1,23,37,3,19,51,17,1,33,39,6,1,175,3,22,252,234,254,251,1,45,39,200, +200,39,1,184,254,250,131,1,14,200,200,57,254,54,1,6,131,2,185,1,144,252,223,1,145,254,225,1,30,1,31,187,187,254,225,254,226,2,61,253,195,187,0,0,1,0,72,255,211,4,136,2,74,0,5,0,0,5,1,55,9,1,23,2,104,253,224,72,1,216,1,216,72,45,2,45,74,254,28,1,228,74, +0,0,1,0,88,0,0,4,121,5,4,0,11,0,0,1,33,53,33,21,33,17,33,21,33,53,33,2,20,254,68,4,33,254,68,1,188,251,223,1,188,4,90,170,170,252,80,170,170,0,2,1,0,255,52,3,209,6,161,0,3,0,7,0,0,5,33,17,33,3,17,33,17,1,114,1,237,254,19,114,2,209,90,6,137,249,5,7,109, +248,147,0,0,0,4,0,6,255,52,4,203,6,161,0,3,0,7,0,11,0,15,0,0,23,17,33,17,37,33,17,33,53,33,53,33,53,33,17,33,6,4,197,251,173,3,225,252,31,3,225,252,31,3,225,252,31,204,7,109,248,147,114,1,186,172,236,170,2,141,0,0,0,5,0,6,255,52,4,203,6,161,0,3,0,7,0, +11,0,15,0,19,0,0,1,51,21,35,17,51,21,35,1,17,33,17,37,33,17,33,53,33,17,33,1,238,245,245,245,245,254,24,4,197,251,173,3,225,252,31,3,225,252,31,4,111,246,254,18,245,254,158,7,109,248,147,114,2,135,170,3,88,0,4,0,6,255,52,4,203,6,161,0,3,0,8,0,12,0,17, +0,0,19,9,3,33,17,9,2,33,17,33,9,2,17,33,195,1,165,1,166,254,90,254,16,3,225,254,15,254,16,4,83,251,59,4,197,251,173,1,240,1,241,252,31,2,220,254,90,1,166,1,166,251,36,2,196,254,16,1,240,252,202,7,109,252,173,1,240,254,16,2,225,0,255,255,0,6,255,52,4, +203,6,161,16,38,13,15,0,0,16,6,9,63,0,0,0,0,0,4,0,6,255,52,4,203,6,161,0,13,0,24,0,28,0,39,0,0,18,16,23,22,51,50,55,54,16,39,38,35,34,7,3,33,17,6,7,6,35,34,39,38,39,1,33,17,33,1,54,55,54,51,50,23,22,23,17,33,128,244,122,122,122,122,245,245,122,122,122, +122,252,3,225,73,119,153,152,153,152,119,72,4,83,251,59,4,197,251,173,72,119,152,153,152,153,119,73,252,31,3,245,253,206,141,71,71,141,2,50,141,71,71,251,36,1,202,95,69,88,88,69,94,253,197,7,109,253,168,95,68,88,88,69,95,1,231,0,0,0,3,0,6,254,162,4,203, +7,51,0,19,0,27,0,35,0,0,18,16,37,54,55,17,51,17,22,23,4,16,5,6,7,17,35,17,38,39,2,16,23,22,23,17,6,7,37,17,54,55,54,16,39,38,6,1,49,114,115,152,114,115,1,50,254,206,115,114,152,115,114,183,244,84,84,84,84,1,64,84,84,245,245,84,1,124,2,192,176,66,17,1, +244,254,12,17,66,176,253,64,176,66,17,254,41,1,215,17,66,3,41,253,206,141,49,15,3,204,15,49,64,252,52,15,49,141,2,50,141,49,0,0,255,255,0,6,0,116,4,203,5,68,16,38,13,15,0,0,16,7,10,34,0,0,0,200,0,1,0,88,255,66,4,121,5,213,0,11,0,0,1,51,1,33,21,33,1,35, +1,33,53,33,3,121,190,254,154,1,168,254,9,254,163,191,1,93,254,149,1,187,5,213,253,2,170,253,21,2,235,170,0,0,0,1,0,88,255,66,4,121,5,213,0,11,0,0,9,1,51,1,33,21,33,1,35,1,33,53,1,204,254,154,191,1,102,1,238,254,97,1,93,190,254,163,254,60,2,215,2,254, +253,2,170,253,21,2,235,170,0,3,0,6,255,52,4,203,6,161,0,3,0,6,0,9,0,0,23,17,33,17,37,1,33,5,1,33,6,4,197,251,173,3,89,252,167,3,225,252,158,3,98,204,7,109,248,147,198,6,53,65,249,184,0,0,0,3,0,6,255,52,4,203,6,161,0,3,0,6,0,9,0,0,5,33,17,33,3,17,33,7, +17,33,4,203,251,59,4,197,114,252,167,136,3,98,204,7,109,249,89,6,53,65,249,184,0,0,0,4,0,6,255,52,4,203,6,161,0,3,0,7,0,11,0,14,0,0,23,17,33,17,37,33,17,1,53,1,17,33,1,17,1,6,4,197,251,173,3,225,252,31,3,225,252,31,3,225,252,206,204,7,109,248,147,114, +1,88,1,136,192,1,136,1,97,251,133,2,101,254,204,0,0,0,0,4,0,6,255,52,4,203,6,161,0,3,0,7,0,10,0,14,0,0,23,17,33,17,37,33,17,1,25,1,9,2,17,33,6,4,197,251,173,3,225,252,31,3,50,252,206,3,225,252,31,204,7,109,248,147,114,2,224,254,120,3,27,253,155,1,49, +1,233,254,120,2,233,0,0,0,0,1,0,66,254,162,4,143,7,51,0,17,0,0,19,53,1,23,7,33,17,51,17,33,21,33,17,35,17,33,23,7,66,1,35,90,160,1,67,152,1,149,254,107,152,254,189,160,90,2,170,70,1,35,90,160,4,26,251,230,164,252,45,3,211,160,90,0,0,1,0,66,254,162,4, +143,7,51,0,17,0,0,9,1,39,55,33,17,35,17,33,53,33,17,51,17,33,39,55,1,4,143,254,221,90,160,254,188,152,254,108,1,148,152,1,68,160,90,1,35,2,158,254,221,90,160,252,45,3,211,164,4,26,251,230,160,90,254,221,0,0,3,0,6,255,52,4,203,6,161,0,3,0,10,0,17,0,0, +23,17,33,17,37,33,17,33,23,7,1,53,1,23,7,33,17,33,6,4,197,251,173,3,225,252,238,160,90,254,235,1,21,90,160,3,18,252,31,204,7,109,248,147,114,2,207,160,90,1,21,110,1,21,90,160,3,22,0,3,0,6,255,52,4,203,6,161,0,3,0,10,0,17,0,0,5,33,17,33,3,17,1,39,55,33, +17,1,17,33,17,33,39,55,4,203,251,59,4,197,114,254,235,90,160,252,238,3,225,252,31,3,18,160,90,204,7,109,249,5,2,234,254,235,90,160,253,49,3,88,3,49,252,234,160,90,0,0,0,3,0,6,255,196,4,203,5,213,0,8,0,30,0,39,0,0,19,16,23,22,51,50,55,1,6,1,6,35,34,39, +36,17,16,37,39,51,23,54,51,50,23,4,17,16,5,19,35,9,1,54,17,16,39,38,35,34,128,244,122,122,61,62,254,108,207,2,150,87,87,153,152,254,207,1,21,115,191,80,89,88,152,153,1,50,254,231,129,190,254,118,1,148,210,245,122,122,62,2,220,254,231,141,71,18,3,106, +140,252,178,29,88,176,1,96,1,79,176,250,174,29,88,176,254,160,254,175,176,254,233,4,242,252,149,140,1,5,1,25,141,71,0,0,0,2,0,88,255,52,4,121,5,4,0,3,0,11,0,0,5,21,33,53,1,17,33,21,33,53,33,17,4,121,251,223,2,101,1,188,251,223,1,189,90,114,114,5,94,251, +166,170,170,4,90,0,0,3,0,37,254,162,4,172,7,51,0,11,0,14,0,17,0,0,1,17,51,17,51,1,33,17,35,17,33,1,19,17,3,33,51,3,2,28,152,47,1,201,254,8,152,254,9,1,201,46,246,1,142,246,246,5,213,1,94,254,162,250,43,254,162,1,94,5,213,250,213,3,107,252,149,3,107,0, +0,0,0,3,0,6,255,52,4,203,6,161,0,4,0,8,0,14,0,0,19,17,9,1,17,55,17,33,17,19,17,33,17,1,35,120,1,240,1,241,114,251,59,114,3,225,254,99,166,6,47,254,237,251,179,4,75,1,21,114,248,147,7,109,252,236,252,25,3,229,252,117,0,0,0,4,0,6,255,52,4,203,6,161,0,2, +0,6,0,11,0,17,0,0,37,9,2,17,33,17,37,33,53,48,33,53,1,51,1,17,33,3,138,254,222,254,222,254,192,4,197,251,173,3,225,252,31,1,130,221,1,130,252,31,170,4,121,251,135,254,138,7,109,248,147,114,90,91,5,122,250,134,5,212,0,3,0,88,0,0,4,121,5,4,0,3,0,27,0,31, +0,0,1,6,20,23,21,38,39,38,52,55,54,55,17,51,17,22,23,22,20,7,6,7,17,33,21,33,53,33,19,54,52,39,2,20,60,60,60,46,76,77,46,59,168,60,43,80,78,46,59,1,189,251,223,1,188,168,61,61,3,82,45,147,42,137,18,47,75,225,79,47,19,1,39,254,217,20,45,84,214,81,48,18, +254,203,170,170,1,190,49,139,46,0,0,0,0,1,0,88,0,0,4,121,6,14,0,17,0,0,9,1,7,39,17,33,21,33,17,35,17,33,53,33,17,7,39,1,2,146,1,34,90,160,1,191,254,65,164,254,66,1,190,160,90,1,36,6,14,254,221,90,160,253,238,170,253,139,2,117,170,2,18,160,90,1,35,0,0, +3,0,6,255,52,4,203,6,161,0,3,0,10,0,17,0,0,19,33,17,33,37,33,17,33,1,7,39,3,17,7,39,1,33,17,6,4,197,251,59,2,180,1,159,254,71,1,20,90,160,164,160,90,1,20,254,72,6,161,248,147,114,6,137,254,236,90,160,250,69,5,187,160,90,1,20,249,119,0,0,2,0,88,0,0,4, +121,5,246,0,3,0,11,0,0,19,33,21,33,1,17,33,53,33,21,33,17,88,4,33,251,223,1,188,254,68,4,33,254,67,5,246,148,250,158,4,90,170,170,251,166,0,3,0,37,254,162,4,172,7,51,0,11,0,14,0,17,0,0,33,35,1,33,17,51,17,33,1,35,17,35,17,35,27,1,17,19,2,28,46,254,55, +1,247,152,1,248,254,55,47,152,246,246,152,246,5,213,1,94,254,162,250,43,254,162,6,137,252,149,3,107,252,149,3,107,0,0,0,3,0,6,255,52,4,203,6,161,0,4,0,8,0,14,0,0,23,33,17,9,2,33,17,33,9,1,51,1,17,33,120,3,225,254,15,254,16,4,83,251,59,4,197,251,173,1, +158,166,1,157,252,31,90,1,21,4,75,251,179,254,123,7,109,251,167,3,141,252,117,3,229,0,0,0,0,4,0,6,255,52,4,203,6,161,0,2,0,6,0,12,0,16,0,0,1,33,9,1,17,33,17,37,33,17,1,35,1,53,33,53,33,3,138,253,188,1,34,253,158,4,197,251,173,3,225,254,126,221,254,126, +3,225,252,31,5,43,251,135,254,130,7,109,248,147,114,5,212,250,134,5,122,91,90,0,0,3,0,88,0,0,4,121,5,4,0,23,0,28,0,33,0,0,1,53,33,53,33,21,33,21,22,23,22,20,7,6,7,17,35,17,38,39,38,52,55,54,19,54,53,52,39,35,6,21,20,23,2,20,254,68,4,33,254,67,60,43,80, +78,46,59,168,60,46,76,77,46,227,61,61,168,60,60,3,221,125,170,170,125,20,45,84,215,80,47,18,254,32,1,224,18,46,76,224,79,47,254,159,47,65,74,47,44,69,78,42,0,0,1,0,88,0,0,4,121,6,14,0,17,0,0,33,1,55,23,17,33,53,33,17,51,17,33,21,33,17,55,23,1,2,64,254, +220,90,160,254,66,1,190,164,1,191,254,65,160,90,254,222,1,35,90,160,1,152,170,2,239,253,17,170,254,104,160,90,254,221,0,0,0,0,3,0,6,255,52,4,203,6,161,0,3,0,10,0,17,0,0,23,17,33,17,1,17,55,23,1,33,17,41,1,17,33,1,55,23,6,4,197,253,239,160,90,254,236, +1,185,253,189,254,98,1,184,254,236,90,160,204,7,109,248,147,6,251,250,69,160,90,254,236,6,137,249,119,1,20,90,160,0,0,255,255,1,0,255,52,3,209,5,213,16,38,13,14,0,0,16,6,0,10,0,0,0,0,255,255,0,6,255,52,4,203,5,213,16,38,13,13,0,0,16,6,2,227,0,0,0,0,255, +255,0,6,255,52,4,203,5,63,16,38,13,13,0,0,16,7,10,30,0,0,0,200,255,255,1,0,255,52,3,209,3,233,16,38,13,14,0,0,16,6,13,15,0,0,0,0,255,255,0,6,255,52,4,203,5,68,16,38,13,13,0,0,16,7,10,34,0,0,0,200,0,3,0,164,0,0,4,44,5,68,0,20,0,28,0,36,0,0,19,52,54,55, +54,51,50,23,30,1,21,17,35,17,52,38,32,6,21,17,35,18,54,50,22,20,6,34,38,36,38,34,6,20,22,50,54,164,52,58,122,220,211,131,58,52,172,136,254,225,136,173,186,154,226,153,156,226,151,1,155,86,117,86,82,121,86,2,230,230,202,56,118,117,52,199,238,253,26,3, +68,214,134,134,214,252,188,3,77,156,155,224,154,151,173,85,84,121,82,84,0,0,255,255,0,6,255,52,4,203,6,161,16,38,0,10,0,0,16,6,9,63,0,0,0,0,255,255,255,236,0,90,4,229,5,94,16,39,10,70,0,0,0,200,16,6,8,183,0,0,255,255,0,6,255,52,4,203,6,161,16,38,0,29, +0,0,16,6,9,63,0,0,0,0,0,3,0,88,0,0,4,121,6,166,0,3,0,7,0,15,0,0,1,51,21,35,37,51,21,35,3,17,33,53,33,21,33,17,1,63,203,203,1,136,202,202,178,254,67,4,33,254,68,6,166,202,202,202,250,36,4,90,170,170,251,166,0,0,0,4,0,0,0,0,4,209,6,166,0,3,0,7,0,11,0,14, +0,0,1,51,21,35,37,51,21,35,5,33,1,35,55,1,33,1,63,203,203,1,136,202,202,253,57,4,209,254,1,210,104,1,119,253,19,6,166,202,202,202,77,250,113,211,4,18,0,0,255,255,1,8,1,155,3,201,5,22,16,39,13,16,0,0,255,6,16,6,8,183,0,0,255,255,1,63,1,212,3,145,5,72, +16,39,13,16,0,0,255,56,16,6,13,15,0,0,255,255,0,6,0,116,4,203,6,166,16,39,13,16,0,0,0,150,16,7,10,34,0,0,0,200,0,0,0,1,0,164,254,162,4,44,7,51,0,43,0,0,19,17,51,17,20,23,22,23,22,23,22,23,17,51,17,54,55,54,55,54,55,54,53,17,51,17,20,7,6,7,6,7,6,7,17, +35,17,38,39,38,39,38,39,38,164,173,12,4,13,18,86,32,38,152,35,36,75,29,7,10,12,172,24,29,57,66,85,53,62,152,61,53,94,58,59,26,25,2,94,2,68,253,96,49,111,37,34,46,43,16,7,6,136,249,121,7,15,32,57,13,58,67,91,2,162,253,188,238,92,108,51,59,29,18,7,254, +158,1,98,7,18,32,56,57,104,98,0,2,0,88,254,162,4,121,7,51,0,19,0,28,0,0,1,33,21,33,17,35,17,34,39,38,16,55,54,51,17,51,17,33,21,33,3,17,34,7,6,21,20,23,22,2,180,1,197,254,59,152,184,129,139,139,129,184,152,1,197,254,59,152,121,86,95,95,87,1,57,150,253, +255,2,2,138,149,1,124,149,138,2,213,253,43,149,253,113,2,142,95,105,127,128,104,95,0,0,0,255,255,0,88,1,236,4,121,5,72,16,39,13,16,0,0,255,56,16,6,0,97,0,0,255,255,0,88,0,141,4,121,5,72,16,39,13,16,0,0,255,56,16,6,0,33,0,0,0,2,0,88,254,225,4,121,2,215, +0,3,0,9,0,0,19,33,21,33,5,51,21,3,35,19,88,4,33,251,223,1,158,252,197,154,99,2,215,170,254,207,254,129,1,127,0,0,0,3,0,37,0,0,4,172,5,213,0,10,0,32,0,42,0,0,1,33,19,22,23,22,23,22,23,22,23,37,21,6,7,6,7,3,35,3,6,7,6,7,53,54,55,3,33,3,54,55,54,5,27,1, +38,39,38,39,38,39,38,3,170,253,124,122,42,40,50,74,11,22,69,60,1,105,75,72,35,38,186,245,217,23,22,71,73,74,69,194,4,135,216,11,11,69,253,162,151,124,45,50,23,10,77,51,10,5,43,254,79,2,9,11,31,5,10,33,13,114,174,59,27,14,7,253,159,2,198,6,10,29,63,174, +57,27,2,121,253,63,5,5,30,112,253,230,1,184,13,22,10,4,33,12,2,0,0,3,0,88,255,227,4,121,5,240,0,23,0,42,0,61,0,0,0,32,23,22,19,54,55,21,6,7,2,7,6,32,39,38,3,6,7,53,54,55,18,55,37,34,7,6,7,54,51,50,22,23,22,23,22,51,50,55,2,39,38,1,18,23,22,51,50,55,54, +55,6,35,34,39,38,39,46,1,35,34,1,121,1,222,123,104,15,24,24,23,23,9,112,123,254,34,122,105,15,23,24,23,23,9,112,1,105,141,69,53,13,27,28,53,100,74,11,22,116,93,16,17,3,66,70,254,90,3,67,69,141,142,70,52,13,22,23,90,113,23,10,77,103,51,23,5,240,196,167, +254,208,17,20,174,18,15,254,176,180,196,196,168,1,49,17,21,174,18,15,1,80,179,36,152,115,206,3,22,31,5,10,55,2,1,37,146,152,253,130,254,219,146,152,152,115,206,2,51,10,4,33,24,0,0,0,1,0,88,254,162,4,121,7,51,0,31,0,0,1,21,14,1,35,34,39,17,35,17,38,39, +38,35,34,6,7,53,62,1,51,50,23,22,23,17,51,17,22,51,50,54,4,121,75,143,79,71,85,152,31,25,52,51,79,141,73,78,146,83,53,50,19,23,152,94,78,70,137,3,122,174,59,55,32,252,40,4,21,11,6,12,59,63,174,60,54,11,4,7,3,207,251,243,39,61,0,2,1,0,254,225,3,209,4, +39,0,3,0,17,0,0,1,51,17,35,19,51,21,7,33,21,33,7,35,55,35,53,51,55,1,233,252,252,13,252,96,1,63,254,135,43,154,21,168,198,48,4,39,254,209,254,55,207,186,114,83,83,114,186,0,3,0,6,255,52,4,203,6,161,0,3,0,7,0,27,0,0,23,33,17,33,3,17,33,17,1,33,19,23,7, +51,21,33,7,33,21,33,3,39,55,35,53,33,55,33,120,3,225,252,31,114,4,197,251,247,2,5,197,100,131,162,254,245,147,1,158,253,251,199,100,131,160,1,8,147,254,101,90,6,137,249,5,7,109,248,147,4,110,1,59,102,213,170,236,172,254,197,104,211,172,236,0,0,255,255, +0,6,255,52,4,203,6,161,16,38,0,34,0,0,16,6,9,63,0,0,0,0,0,2,0,88,0,0,4,121,4,162,0,22,0,27,0,0,19,54,55,3,51,19,30,1,23,19,51,3,54,55,21,14,1,35,3,35,3,6,7,37,27,1,46,1,88,104,90,118,191,114,77,151,39,141,191,147,104,120,58,148,66,138,237,172,120,118, +1,176,96,77,26,93,2,154,80,20,1,164,254,100,10,72,13,1,251,253,244,18,100,174,45,68,254,19,2,98,15,103,100,254,166,1,21,10,42,0,0,0,0,2,0,88,0,0,4,121,4,162,0,22,0,27,0,0,19,54,51,19,51,19,50,54,55,21,6,7,19,35,3,46,1,39,3,35,19,6,7,37,39,7,30,1,88,149, +147,114,237,148,60,143,59,111,106,140,191,141,47,101,69,164,191,172,125,123,2,83,67,53,69,37,2,154,114,1,150,253,240,73,49,174,86,21,254,13,1,253,14,47,22,253,176,2,100,14,106,207,241,190,25,20,0,0,255,255,1,54,0,0,3,207,4,96,16,6,3,7,0,0,255,255,0,190, +254,86,4,84,4,123,16,6,3,15,0,0,255,255,0,70,255,227,4,140,4,96,16,6,3,23,0,0,255,255,0,6,255,52,4,203,4,121,16,38,13,13,0,0,16,6,2,255,0,0,0,0,255,255,0,156,255,52,4,53,4,123,16,38,13,12,0,0,16,6,3,52,0,0,0,0,255,255,1,0,255,52,3,209,4,96,16,38,13,14, +0,0,16,6,3,7,0,0,0,0,255,255,0,6,255,52,4,203,4,96,16,38,13,13,0,0,16,6,3,23,0,0,0,0,255,255,0,70,255,231,4,149,4,121,16,6,2,255,0,0,0,1,0,26,254,46,4,183,0,181,0,11,0,33,183,6,6,10,8,5,6,1,3,47,220,236,47,220,236,49,0,183,0,182,6,9,2,182,7,4,47,60,236, +50,220,236,48,19,17,35,53,33,17,33,17,33,21,35,17,225,199,1,111,1,191,1,111,199,254,46,1,218,173,254,37,1,219,173,254,38,0,3,0,72,255,211,4,136,4,58,0,5,0,17,0,48,0,0,5,1,55,9,1,23,37,35,34,6,21,20,22,51,50,54,61,1,55,17,35,53,14,1,35,34,38,53,52,54, +59,1,53,52,38,35,34,6,7,53,62,1,51,50,23,22,23,30,1,2,104,253,224,72,1,216,1,216,72,254,24,35,91,93,69,62,86,99,105,105,33,102,72,97,116,142,138,140,76,84,53,109,52,58,106,50,79,56,53,37,22,18,45,2,45,74,254,28,1,228,74,243,63,63,56,63,118,104,23,43, +254,154,93,56,53,108,91,104,109,16,75,68,30,29,103,21,22,23,22,47,28,82,0,0,0,6,0,6,0,218,4,203,4,58,0,3,0,7,0,11,0,15,0,27,0,57,0,0,1,53,51,21,51,53,51,21,33,53,51,21,5,33,53,33,1,35,34,6,21,20,22,51,50,54,61,1,55,17,35,53,14,1,35,34,38,53,52,54,59, +1,53,52,38,35,34,6,7,53,62,1,51,50,22,23,30,1,3,97,115,55,115,254,57,115,1,161,251,59,4,197,252,183,35,91,93,69,62,86,99,105,105,33,102,72,97,116,142,138,140,76,84,53,109,52,58,106,50,79,112,34,22,18,1,184,127,127,127,127,127,127,222,114,1,167,63,63, +56,63,118,104,23,43,254,154,93,56,53,108,91,104,109,16,75,68,30,29,103,21,22,46,46,28,82,0,0,0,0,6,0,6,0,218,4,203,4,58,0,3,0,7,0,19,0,49,0,61,0,91,0,0,37,53,33,21,33,53,33,21,3,35,34,6,21,20,22,51,50,54,61,1,55,17,35,53,14,1,35,34,38,53,52,54,59,1,53, +52,38,35,34,6,7,53,62,1,51,50,22,23,30,1,5,35,34,6,21,20,22,51,50,54,55,53,55,17,35,53,14,1,35,34,38,53,52,54,59,1,53,46,1,35,34,6,7,53,62,1,51,50,22,23,30,1,2,155,2,48,251,59,2,48,180,35,91,93,69,62,86,99,105,105,33,102,72,97,116,142,138,140,76,84,53, +109,52,58,106,50,79,112,34,22,18,1,127,34,91,93,69,62,86,98,1,105,105,34,101,73,97,115,142,138,140,1,76,83,53,109,52,58,106,50,79,112,34,22,18,218,114,114,114,114,2,25,63,63,56,63,118,104,23,43,254,154,93,56,53,108,91,104,109,16,75,68,30,29,103,21,22, +46,46,28,82,125,63,63,56,63,118,104,23,43,254,154,93,56,53,108,91,104,109,16,75,68,30,29,103,21,22,46,46,28,82,0,0,8,0,6,1,107,4,203,4,138,0,30,0,42,0,46,0,50,0,54,0,58,0,62,0,66,0,0,1,17,35,53,14,1,35,34,38,53,52,54,59,1,53,52,38,35,34,6,7,53,62,1,51, +50,23,22,23,30,1,7,35,34,6,21,20,22,51,50,54,61,1,1,21,37,61,1,33,21,33,17,37,21,5,37,21,37,53,1,21,33,53,5,21,5,53,3,113,105,33,102,72,97,116,142,138,140,76,84,53,109,52,58,106,50,79,56,53,37,22,18,209,35,91,93,69,62,86,99,1,202,254,212,1,44,254,212, +1,44,254,212,253,147,254,212,1,44,254,212,1,44,254,212,3,30,254,154,93,56,53,108,91,104,109,16,75,68,30,29,103,21,22,23,22,47,28,82,125,63,63,56,63,118,104,23,254,241,121,140,121,188,114,1,68,140,121,140,121,121,140,121,254,162,114,114,188,121,140,121, +0,7,0,82,0,56,4,126,4,207,0,52,0,60,0,68,0,76,0,84,0,90,0,96,0,0,37,35,53,38,39,38,39,38,39,7,39,55,38,53,52,55,53,39,55,23,54,55,54,55,54,55,53,51,21,22,23,22,23,22,23,55,23,7,23,22,21,20,7,21,23,7,39,6,7,6,7,6,7,53,54,55,54,55,54,55,39,17,21,55,38, +39,38,39,38,39,6,7,6,7,6,7,23,17,53,7,22,23,22,23,22,39,55,39,6,21,20,37,7,23,54,53,52,2,154,100,51,47,68,57,19,15,177,50,176,28,28,176,50,177,16,18,57,68,47,51,100,52,46,69,57,18,15,177,50,176,1,28,28,175,50,176,16,18,57,69,46,52,31,29,50,42,9,7,168, +168,7,9,42,50,29,131,31,28,50,42,9,8,168,168,8,9,42,50,28,188,169,169,16,2,42,169,169,17,56,203,6,20,29,56,19,19,102,87,102,69,79,80,68,1,102,87,103,20,19,56,29,20,6,203,203,6,20,29,56,18,20,102,87,101,2,68,80,79,69,1,101,87,102,20,18,56,29,20,6,103, +5,12,21,42,9,9,97,1,112,195,97,9,9,42,21,12,5,5,12,21,42,9,9,97,254,144,195,97,9,9,42,21,12,179,98,97,46,52,51,149,97,98,45,52,53,0,0,0,0,4,0,70,0,94,4,138,4,162,0,15,0,30,0,39,0,48,0,0,18,52,62,2,50,30,2,20,14,2,34,46,1,19,51,27,1,51,38,39,46,2,34,14, +1,7,6,5,35,3,54,55,62,1,55,54,1,3,35,22,23,30,1,23,22,70,86,147,202,222,202,147,86,86,147,202,222,202,147,28,240,192,193,239,7,24,34,118,160,178,160,118,34,24,3,90,164,207,56,51,80,118,34,25,254,24,206,165,7,25,34,118,80,51,2,17,222,202,147,86,86,147, +202,222,202,147,86,86,147,1,110,254,152,1,104,60,56,80,118,68,68,118,80,56,162,254,130,8,22,34,118,80,57,254,193,1,126,63,57,80,118,34,22,0,0,5,0,70,0,94,4,138,4,162,0,2,0,18,0,28,0,38,0,48,0,0,1,19,33,0,52,62,2,50,30,2,20,14,2,34,46,1,18,20,30,1,23, +22,23,1,6,7,55,33,38,39,46,1,34,6,7,6,5,1,54,55,62,2,52,39,38,2,104,243,254,26,254,209,86,147,202,222,202,147,86,86,147,202,222,202,147,25,68,118,80,52,55,254,180,4,3,57,2,176,17,19,59,160,178,160,59,19,2,209,254,180,55,52,80,118,68,34,3,1,77,1,199,254, +253,222,202,147,86,86,147,202,222,202,147,86,86,147,1,146,178,160,118,34,22,8,2,105,8,9,99,21,19,59,68,68,59,19,103,253,151,8,22,34,118,160,178,80,9,0,0,0,0,3,0,70,0,94,4,138,4,162,0,2,0,9,0,37,0,0,1,55,39,23,1,7,1,7,3,5,1,51,20,30,2,50,62,2,52,46,2, +35,53,50,30,2,20,14,2,34,46,2,1,5,145,174,205,1,238,86,254,18,151,70,1,202,253,250,111,68,118,160,178,160,118,68,68,118,160,89,111,202,147,86,86,147,202,222,202,147,86,3,83,146,28,119,254,18,86,1,238,151,1,202,70,254,95,89,160,118,68,68,118,160,178,160, +118,68,111,86,147,202,222,202,147,86,86,147,202,0,0,2,0,6,255,52,4,203,6,161,0,3,0,7,0,0,23,33,17,33,3,17,33,17,120,3,225,252,31,114,4,197,90,6,137,249,5,7,109,248,147,0,0,0,0,1,1,24,253,240,3,184,7,134,0,11,0,0,1,35,53,16,19,18,19,51,0,3,2,17,1,219, +195,160,186,166,160,254,252,90,127,253,240,234,3,151,1,226,2,48,1,3,253,243,254,134,253,238,252,237,0,1,1,24,253,252,1,219,7,137,0,3,0,0,1,51,17,35,1,24,195,195,7,137,246,115,0,0,0,1,1,24,254,20,3,184,7,137,0,11,0,0,1,21,16,19,18,19,35,2,3,2,17,53,1, +219,127,147,203,160,208,144,160,7,137,234,252,165,254,87,254,20,254,101,1,69,1,238,2,37,3,51,234,0,0,1,1,25,253,240,3,185,7,134,0,11,0,0,1,53,16,3,2,1,51,18,19,18,17,21,2,246,127,90,254,252,160,166,186,160,253,240,234,3,19,2,18,1,122,2,13,254,253,253, +208,254,30,252,105,234,0,1,2,246,253,252,3,185,7,137,0,4,0,0,1,17,35,17,48,3,185,195,7,137,246,115,9,141,0,1,1,25,254,20,3,185,7,137,0,11,0,0,1,51,21,16,3,2,3,35,18,19,18,17,2,246,195,160,144,208,160,203,147,127,7,137,234,252,205,253,219,254,18,254,187, +1,155,1,236,1,169,3,91,0,0,1,1,24,253,252,3,184,7,109,0,5,0,0,1,35,17,33,21,33,1,219,195,2,160,254,35,253,252,9,113,195,0,1,1,24,253,252,1,219,7,137,0,3,0,0,1,51,17,35,1,24,195,195,7,137,246,115,0,0,0,1,1,24,254,20,3,184,7,137,0,5,0,0,1,17,33,21,33,17, +1,219,1,221,253,96,7,137,247,78,195,9,117,0,0,0,0,1,1,24,253,252,3,184,7,109,0,5,0,0,1,17,33,53,33,17,2,245,254,35,2,160,253,252,8,174,195,246,143,0,0,0,0,1,2,245,253,252,3,184,7,122,0,3,0,0,1,51,17,35,2,245,195,195,7,122,246,130,0,0,0,1,1,24,254,20, +3,184,7,122,0,5,0,0,1,51,17,33,53,33,2,245,195,253,96,1,221,7,122,246,154,195,0,1,2,12,253,234,4,193,7,109,0,13,0,0,1,35,17,52,55,54,51,33,21,33,34,7,6,21,2,198,186,111,121,186,1,19,254,231,101,68,57,253,234,7,117,223,145,158,176,102,87,153,0,1,0,17, +253,252,2,198,7,134,0,24,0,0,1,22,23,22,25,1,35,17,16,39,38,37,39,53,51,32,55,54,25,1,51,17,16,7,6,1,253,58,42,101,186,110,75,254,251,61,61,1,3,77,110,186,101,40,2,193,32,61,147,254,67,253,232,2,12,1,183,95,65,4,1,187,69,99,1,179,2,12,253,232,254,72, +152,60,0,1,2,12,254,20,4,193,7,134,0,13,0,0,1,17,20,23,22,51,33,21,33,34,39,38,53,17,2,198,57,68,101,1,25,254,237,184,123,111,7,134,248,148,154,86,102,176,158,143,225,7,100,0,0,0,0,1,2,12,253,244,2,198,7,140,0,3,0,0,1,35,17,51,2,198,186,186,253,244,9, +152,0,0,0,1,0,16,253,234,2,197,7,109,0,13,0,0,1,17,52,39,38,35,33,53,33,50,23,22,21,17,2,11,57,68,101,254,231,1,19,186,121,111,253,234,7,125,153,87,102,176,158,145,223,248,139,0,0,0,0,1,2,11,253,252,4,192,7,134,0,24,0,0,1,38,39,38,25,1,51,17,16,23,22, +33,51,21,7,4,7,6,25,1,35,17,16,55,54,2,212,60,40,101,186,110,77,1,3,61,61,254,251,75,110,186,101,42,2,193,33,60,152,1,184,2,24,253,244,254,77,99,69,187,1,4,65,95,254,73,253,244,2,24,1,189,147,61,0,1,0,16,254,20,2,197,7,134,0,13,0,0,1,51,17,20,7,6,35, +33,53,33,50,55,54,53,2,11,186,111,123,184,254,237,1,25,101,68,57,7,134,248,156,225,143,158,176,102,86,154,0,1,2,1,254,0,2,199,7,137,0,3,0,0,1,17,51,17,2,1,198,254,0,9,137,246,119,0,0,2,0,25,0,188,4,143,4,118,0,8,0,17,0,0,37,9,1,21,33,17,33,17,33,1,33, +53,7,23,53,33,17,35,1,142,254,139,1,117,1,169,1,88,252,255,1,239,253,194,194,194,3,10,204,188,1,117,1,117,201,1,153,253,15,1,18,93,195,195,93,2,101,0,0,0,0,2,0,6,0,0,4,203,4,196,0,2,0,6,0,0,1,33,9,1,33,17,33,4,203,251,59,2,98,2,99,251,59,4,197,2,160, +2,36,251,60,1,248,0,0,1,0,150,254,46,4,58,0,181,0,7,0,28,183,4,6,6,9,3,6,1,8,16,220,236,16,220,236,49,0,180,0,182,4,6,2,47,60,220,236,48,19,17,51,17,33,17,51,17,150,168,2,84,168,254,46,2,135,254,37,1,219,253,121,0,0,0,0,1,255,236,2,106,4,229,3,22,0,3, +0,0,3,53,33,21,20,4,249,2,106,172,172,0,0,0,0,1,255,236,2,20,4,229,3,108,0,3,0,0,3,17,33,17,20,4,249,2,20,1,88,254,168,0,0,1,2,24,254,0,2,184,7,129,0,3,0,0,1,17,51,17,2,24,160,254,0,9,129,246,127,0,0,1,1,200,254,0,3,8,7,129,0,3,0,0,1,17,33,17,1,200,1, +64,254,0,9,129,246,127,0,3,0,60,2,106,4,149,3,22,0,3,0,7,0,11,0,0,1,53,33,21,33,53,33,21,33,53,33,21,3,114,1,35,253,66,1,35,253,66,1,35,2,106,172,172,172,172,172,172,0,0,0,3,0,60,2,20,4,149,3,108,0,3,0,7,0,11,0,0,1,17,33,17,33,17,33,17,33,17,33,17,3, +114,1,35,253,66,1,35,253,66,1,35,2,20,1,88,254,168,1,88,254,168,1,88,254,168,0,3,2,24,254,109,2,184,7,19,0,3,0,7,0,11,0,0,1,17,51,17,3,17,51,17,3,17,51,17,2,24,160,160,160,160,160,254,109,2,106,253,150,3,30,2,106,253,150,3,30,2,106,253,150,0,0,3,1,200, +254,109,3,8,7,19,0,3,0,7,0,11,0,0,1,17,33,17,1,17,33,17,1,17,33,17,1,200,1,64,254,192,1,64,254,192,1,64,254,109,2,106,253,150,3,30,2,106,253,150,3,30,2,106,253,150,0,4,0,60,2,106,4,149,3,22,0,3,0,7,0,11,0,15,0,0,19,53,51,21,51,53,51,21,51,53,51,21,51, +53,51,21,60,188,120,188,120,188,120,189,2,106,172,172,172,172,172,172,172,172,0,0,0,4,0,60,2,20,4,149,3,108,0,3,0,7,0,11,0,15,0,0,19,17,51,17,51,17,51,17,51,17,51,17,51,17,51,17,60,188,120,188,120,188,120,189,2,20,1,88,254,168,1,88,254,168,1,88,254,168, +1,88,254,168,0,0,0,4,2,24,254,110,2,184,7,18,0,3,0,7,0,11,0,15,0,0,1,17,51,17,3,17,51,17,3,17,51,17,3,17,51,17,2,24,160,160,160,160,160,160,160,5,112,1,162,254,94,248,254,1,162,254,94,4,172,1,162,254,94,253,170,1,162,254,94,0,0,0,0,4,1,200,254,110,3, +8,7,18,0,3,0,7,0,11,0,15,0,0,1,17,33,17,1,17,33,17,1,17,33,17,1,17,33,17,1,200,1,64,254,192,1,64,254,192,1,64,254,192,1,64,5,112,1,162,254,94,248,254,1,162,254,94,4,172,1,162,254,94,253,170,1,162,254,94,0,1,2,24,254,0,4,229,3,22,0,5,0,0,1,17,33,21,33, +17,2,24,2,205,253,211,254,0,5,22,172,251,150,0,0,0,0,1,2,24,254,0,4,229,3,108,0,5,0,0,1,17,33,17,33,17,2,24,2,205,253,211,254,0,5,108,254,168,251,236,0,0,0,1,1,200,254,0,4,229,3,22,0,5,0,0,1,17,33,21,33,17,1,200,3,29,254,35,254,0,5,22,172,251,150,0,0, +0,0,1,1,200,254,0,4,229,3,108,0,5,0,0,1,17,33,17,33,17,1,200,3,29,254,35,254,0,5,108,254,168,251,236,0,0,0,1,255,236,254,0,2,184,3,22,0,5,0,0,1,17,33,53,33,17,2,24,253,212,2,204,254,0,4,106,172,250,234,0,0,0,0,1,255,236,254,0,2,184,3,108,0,5,0,0,1,17, +33,17,33,17,2,24,253,212,2,204,254,0,4,20,1,88,250,148,0,0,0,1,255,236,254,0,3,8,3,22,0,5,0,0,1,17,33,53,33,17,1,200,254,36,3,28,254,0,4,106,172,250,234,0,0,0,0,1,255,236,254,0,3,8,3,108,0,5,0,0,1,17,33,17,33,17,1,200,254,36,3,28,254,0,4,20,1,88,250, +148,0,0,0,1,2,24,2,106,4,229,7,129,0,5,0,0,1,17,51,17,33,21,2,24,160,2,45,2,106,5,23,251,149,172,0,1,2,24,2,20,4,229,7,129,0,5,0,0,1,17,51,17,33,17,2,24,160,2,45,2,20,5,109,251,235,254,168,0,0,0,0,1,1,200,2,106,4,229,7,129,0,5,0,0,1,17,33,17,33,21,1, +200,1,64,1,221,2,106,5,23,251,149,172,0,0,0,0,1,1,200,2,20,4,229,7,129,0,5,0,0,1,17,33,17,33,17,1,200,1,64,1,221,2,20,5,109,251,235,254,168,0,0,0,1,255,236,2,106,2,184,7,129,0,5,0,0,3,53,33,17,51,17,20,2,44,160,2,106,172,4,107,250,233,0,0,1,255,236,2, +20,2,184,7,129,0,5,0,0,3,17,33,17,51,17,20,2,44,160,2,20,1,88,4,21,250,147,0,1,255,236,2,106,3,8,7,129,0,5,0,0,3,53,33,17,33,17,20,1,220,1,64,2,106,172,4,107,250,233,0,1,255,236,2,20,3,8,7,129,0,5,0,0,3,17,33,17,33,17,20,1,220,1,64,2,20,1,88,4,21,250, +147,0,0,0,0,1,2,24,254,0,4,229,7,129,0,7,0,0,1,17,51,17,33,21,33,17,2,24,160,2,45,253,211,254,0,9,129,251,149,172,251,150,0,0,0,1,2,24,254,0,4,229,7,129,0,7,0,0,1,17,51,17,33,17,33,17,2,24,160,2,45,253,211,254,0,9,129,251,235,254,168,251,236,0,0,1,1, +200,254,0,4,229,7,129,0,9,0,0,1,17,35,17,33,17,33,21,33,17,2,24,80,1,64,1,221,253,211,254,0,4,106,5,23,251,149,172,251,150,0,1,1,200,254,0,4,229,7,129,0,9,0,0,1,17,51,17,51,17,33,21,33,17,1,200,80,160,2,45,254,35,254,0,5,22,4,107,251,149,172,251,150, +0,0,1,1,200,254,0,4,229,7,129,0,7,0,0,1,17,33,17,33,21,33,17,1,200,1,64,1,221,254,35,254,0,9,129,251,149,172,251,150,0,0,1,1,200,254,0,4,229,7,129,0,9,0,0,1,17,35,17,33,17,33,17,33,17,2,24,80,1,64,1,221,253,211,254,0,4,20,5,109,251,235,254,168,251,236, +0,0,0,0,1,1,200,254,0,4,229,7,129,0,9,0,0,1,17,51,17,51,17,33,17,33,17,1,200,80,160,2,45,254,35,254,0,5,108,4,21,251,235,254,168,251,236,0,1,1,200,254,0,4,229,7,129,0,7,0,0,1,17,33,17,33,17,33,17,1,200,1,64,1,221,254,35,254,0,9,129,251,235,254,168,251, +236,0,1,255,236,254,0,2,184,7,129,0,7,0,0,1,17,33,53,33,17,51,17,2,24,253,212,2,44,160,254,0,4,106,172,4,107,246,127,0,0,0,1,255,236,254,0,2,184,7,129,0,7,0,0,1,17,33,17,33,17,51,17,2,24,253,212,2,44,160,254,0,4,20,1,88,4,21,246,127,0,0,1,255,236,254, +0,3,8,7,129,0,9,0,0,1,17,33,53,33,17,33,17,35,17,2,24,253,212,1,220,1,64,80,254,0,4,106,172,4,107,250,233,251,150,0,1,255,236,254,0,3,8,7,129,0,9,0,0,1,17,33,53,33,17,51,17,51,17,1,200,254,36,2,44,160,80,254,0,4,106,172,4,107,251,149,250,234,0,0,1,255, +236,254,0,3,8,7,129,0,7,0,0,1,17,33,53,33,17,33,17,1,200,254,36,1,220,1,64,254,0,4,106,172,4,107,246,127,0,0,1,255,236,254,0,3,8,7,129,0,9,0,0,1,17,33,17,33,17,33,17,35,17,2,24,253,212,1,220,1,64,80,254,0,4,20,1,88,4,21,250,147,251,236,0,0,0,0,1,255, +236,254,0,3,8,7,129,0,9,0,0,1,17,33,17,33,17,51,17,51,17,1,200,254,36,2,44,160,80,254,0,4,20,1,88,4,21,251,235,250,148,0,1,255,236,254,0,3,8,7,129,0,7,0,0,1,17,33,17,33,17,33,17,1,200,254,36,1,220,1,64,254,0,4,20,1,88,4,21,246,127,0,1,255,236,254,0,4, +229,3,22,0,7,0,0,1,17,33,53,33,21,33,17,2,24,253,212,4,249,253,211,254,0,4,106,172,172,251,150,0,0,0,1,255,236,254,0,4,229,3,108,0,9,0,0,1,17,33,17,33,21,33,21,33,17,2,24,253,212,2,204,2,45,253,211,254,0,4,20,1,88,86,172,251,150,0,1,255,236,254,0,4,229, +3,108,0,9,0,0,1,17,33,53,33,53,33,17,33,17,2,24,253,212,2,44,2,205,253,211,254,0,4,106,172,86,254,168,251,236,0,1,255,236,254,0,4,229,3,108,0,7,0,0,1,17,33,17,33,17,33,17,2,24,253,212,4,249,253,211,254,0,4,20,1,88,254,168,251,236,0,1,255,236,254,0,4, +229,3,22,0,7,0,0,1,17,33,53,33,21,33,17,1,200,254,36,4,249,254,35,254,0,4,106,172,172,251,150,0,0,0,1,255,236,254,0,4,229,3,108,0,9,0,0,1,17,33,17,33,21,33,21,33,17,1,200,254,36,3,28,1,221,254,35,254,0,4,20,1,88,86,172,251,150,0,1,255,236,254,0,4,229, +3,108,0,9,0,0,1,17,33,53,33,53,33,17,33,17,1,200,254,36,1,220,3,29,254,35,254,0,4,106,172,86,254,168,251,236,0,1,255,236,254,0,4,229,3,108,0,7,0,0,1,17,33,17,33,17,33,17,1,200,254,36,4,249,254,35,254,0,4,20,1,88,254,168,251,236,0,1,255,236,2,106,4,229, +7,129,0,7,0,0,3,53,33,17,51,17,33,21,20,2,44,160,2,45,2,106,172,4,107,251,149,172,0,1,255,236,2,20,4,229,7,129,0,9,0,0,3,17,33,17,51,17,33,21,33,21,20,2,44,160,2,45,253,211,2,20,1,88,4,21,251,149,172,86,0,0,0,1,255,236,2,20,4,229,7,129,0,9,0,0,3,53,33, +17,51,17,33,17,33,53,20,2,44,160,2,45,253,51,2,106,172,4,107,251,235,254,168,86,0,0,0,1,255,236,2,20,4,229,7,129,0,7,0,0,3,17,33,17,51,17,33,17,20,2,44,160,2,45,2,20,1,88,4,21,251,235,254,168,0,0,0,1,255,236,2,106,4,229,7,129,0,7,0,0,3,53,33,17,33,17, +33,21,20,1,220,1,64,1,221,2,106,172,4,107,251,149,172,0,0,0,0,1,255,236,2,20,4,229,7,129,0,9,0,0,3,17,33,17,33,17,33,21,33,21,20,1,220,1,64,1,221,254,35,2,20,1,88,4,21,251,149,172,86,0,0,1,255,236,2,20,4,229,7,129,0,9,0,0,3,53,33,17,33,17,33,17,33,53, +20,1,220,1,64,1,221,252,227,2,106,172,4,107,251,235,254,168,86,0,0,1,255,236,2,20,4,229,7,129,0,7,0,0,3,17,33,17,33,17,33,17,20,1,220,1,64,1,221,2,20,1,88,4,21,251,235,254,168,0,0,1,255,236,254,0,4,229,7,129,0,11,0,0,1,17,35,17,33,53,33,17,51,17,33,21, +2,184,160,253,212,2,44,160,2,45,2,106,251,150,4,106,172,4,107,251,149,172,0,1,255,236,254,0,4,229,7,129,0,11,0,0,1,17,33,17,33,17,51,17,33,21,33,17,2,24,253,212,2,44,160,2,45,253,211,254,0,4,20,1,88,4,21,251,149,172,251,150,0,0,0,1,255,236,254,0,4,229, +7,129,0,11,0,0,1,17,33,53,33,17,51,17,33,17,33,17,2,24,253,212,2,44,160,2,45,253,211,254,0,4,106,172,4,107,251,235,254,168,251,236,0,0,0,1,255,236,254,0,4,229,7,129,0,11,0,0,1,17,33,17,33,17,51,17,33,17,33,17,2,24,253,212,2,44,160,2,45,253,211,254,0, +4,20,1,88,4,21,251,235,254,168,251,236,0,0,1,255,236,254,0,4,229,7,129,0,11,0,0,1,17,33,53,33,17,33,17,33,21,33,17,2,24,253,212,1,220,1,64,1,221,253,211,254,0,4,106,172,4,107,251,149,172,251,150,0,0,0,1,255,236,254,0,4,229,7,129,0,11,0,0,1,17,33,53,33, +17,51,17,33,21,33,17,1,200,254,36,2,44,160,2,45,254,35,254,0,4,106,172,4,107,251,149,172,251,150,0,0,0,0,1,255,236,254,0,4,229,7,129,0,11,0,0,1,17,33,53,33,17,33,17,33,21,33,17,1,200,254,36,1,220,1,64,1,221,254,35,254,0,4,106,172,4,107,251,149,172,251, +150,0,0,0,1,255,236,254,0,4,229,7,129,0,13,0,0,1,17,33,17,33,17,33,17,33,21,33,21,35,17,2,24,253,212,1,220,1,64,1,221,254,35,80,254,0,4,20,1,88,4,21,251,149,172,86,251,236,0,0,1,255,236,254,0,4,229,7,129,0,13,0,0,1,17,35,53,33,53,33,17,33,17,33,17,33, +17,2,24,80,254,36,1,220,1,64,1,221,253,211,254,0,4,20,86,172,4,107,251,235,254,168,251,236,0,0,1,255,236,254,0,4,229,7,129,0,13,0,0,1,17,33,17,33,17,51,17,51,21,33,21,33,17,1,200,254,36,2,44,160,80,1,221,254,35,254,0,4,20,1,88,4,21,251,235,86,172,251, +150,0,0,0,1,255,236,254,0,4,229,7,129,0,13,0,0,1,17,33,53,33,53,51,17,51,17,33,17,33,17,1,200,254,36,1,220,80,160,2,45,254,35,254,0,4,106,172,86,4,21,251,235,254,168,251,236,0,0,0,1,255,236,254,0,4,229,7,129,0,11,0,0,1,17,33,17,33,17,33,17,33,17,33,17, +2,24,253,212,1,220,1,64,1,221,253,211,254,0,4,20,1,88,4,21,251,235,254,168,251,236,0,1,255,236,254,0,4,229,7,129,0,11,0,0,1,17,33,17,33,17,51,17,33,17,33,17,1,200,254,36,2,44,160,2,45,254,35,254,0,4,20,1,88,4,21,251,235,254,168,251,236,0,0,1,255,236, +254,0,4,229,7,129,0,11,0,0,1,17,33,17,33,17,33,17,33,21,33,17,1,200,254,36,1,220,1,64,1,221,254,35,254,0,4,20,1,88,4,21,251,149,172,251,150,0,0,1,255,236,254,0,4,229,7,129,0,11,0,0,1,17,33,53,33,17,33,17,33,17,33,17,1,200,254,36,1,220,1,64,1,221,254, +35,254,0,4,106,172,4,107,251,235,254,168,251,236,0,0,1,255,236,254,0,4,229,7,129,0,11,0,0,1,17,33,17,33,17,33,17,33,17,33,17,1,200,254,36,1,220,1,64,1,221,254,35,254,0,4,20,1,88,4,21,251,235,254,168,251,236,0,2,0,60,2,106,4,149,3,22,0,3,0,7,0,0,19,53, +33,21,51,53,33,21,60,1,240,121,1,240,2,106,172,172,172,172,0,2,0,60,2,20,4,149,3,108,0,3,0,7,0,0,1,17,33,17,33,17,33,17,2,165,1,240,251,167,1,240,2,20,1,88,254,168,1,88,254,168,0,0,0,2,2,24,254,192,2,184,6,193,0,3,0,7,0,0,1,17,51,17,3,17,51,17,2,24,160, +160,160,3,108,3,85,252,171,251,84,3,84,252,172,0,0,0,0,2,1,200,254,192,3,8,6,193,0,3,0,7,0,0,1,17,33,17,1,17,33,17,1,200,1,64,254,192,1,64,3,108,3,85,252,171,251,84,3,84,252,172,0,2,255,236,1,190,4,229,3,194,0,3,0,7,0,0,3,53,33,21,1,53,33,21,20,4,249, +251,7,4,249,3,22,172,172,254,168,172,172,0,0,2,1,120,254,0,3,88,7,129,0,3,0,7,0,0,1,17,51,17,51,17,51,17,1,120,160,160,160,254,0,9,129,246,127,9,129,246,127,0,0,1,2,24,254,0,4,229,3,194,0,9,0,0,1,17,33,21,33,21,33,21,33,17,2,24,2,205,253,211,2,45,253, +211,254,0,5,194,172,172,172,252,66,0,0,1,1,120,254,0,4,229,3,22,0,9,0,0,1,17,33,21,33,17,35,17,35,17,1,120,3,109,254,115,160,160,254,0,5,22,172,251,150,4,106,251,150,0,0,2,1,120,254,0,4,229,3,194,0,5,0,11,0,0,1,17,33,21,33,17,51,17,33,21,33,17,1,120, +3,109,253,51,160,2,45,254,115,254,0,5,194,172,250,234,4,106,172,252,66,0,0,1,255,236,254,0,2,184,3,194,0,9,0,0,1,17,33,53,33,53,33,53,33,17,2,24,253,212,2,44,253,212,2,204,254,0,3,190,172,172,172,250,62,0,0,1,255,236,254,0,3,88,3,22,0,9,0,0,3,53,33,17, +35,17,35,17,35,17,20,3,108,160,160,160,2,106,172,250,234,4,106,251,150,4,106,0,0,0,0,2,255,236,254,0,3,88,3,194,0,5,0,11,0,0,1,17,33,53,33,17,33,17,33,53,33,17,2,184,253,52,3,108,254,32,254,116,2,44,254,0,5,22,172,250,62,3,190,172,251,150,0,1,2,24,1, +190,4,229,7,129,0,9,0,0,1,17,51,17,33,21,33,21,33,21,2,24,160,2,45,253,211,2,45,1,190,5,195,252,65,172,172,172,0,0,0,1,1,120,2,106,4,229,7,129,0,9,0,0,1,17,51,17,51,17,51,17,33,21,1,120,160,160,160,1,141,2,106,5,23,251,149,4,107,251,149,172,0,0,0,2,1, +120,1,190,4,229,7,129,0,5,0,11,0,0,1,17,51,17,33,21,1,17,51,17,33,21,2,184,160,1,141,252,147,160,2,205,3,22,4,107,252,65,172,254,168,5,195,250,233,172,0,1,255,236,1,190,2,184,7,129,0,9,0,0,3,53,33,53,33,53,33,17,51,17,20,2,44,253,212,2,44,160,1,190,172, +172,172,3,191,250,61,0,0,0,0,1,255,236,2,106,3,88,7,129,0,9,0,0,3,53,33,17,51,17,51,17,51,17,20,1,140,160,160,160,2,106,172,4,107,251,149,4,107,250,233,0,0,0,0,2,255,236,1,190,3,88,7,129,0,5,0,11,0,0,3,53,33,17,51,17,1,53,33,17,51,17,20,1,140,160,253, +212,2,204,160,3,22,172,3,191,251,149,254,168,172,5,23,250,61,0,0,1,2,24,254,0,4,229,7,129,0,11,0,0,1,17,51,17,33,21,33,21,33,21,33,17,2,24,160,2,45,253,211,2,45,253,211,254,0,9,129,252,65,172,172,172,252,66,0,2,1,120,254,0,4,229,7,129,0,3,0,11,0,0,1, +17,51,17,51,17,51,17,33,21,33,17,1,120,160,160,160,1,141,254,115,254,0,9,129,246,127,9,129,251,149,172,251,150,0,0,0,3,1,120,254,0,4,229,7,129,0,5,0,9,0,15,0,0,1,17,51,17,33,21,1,17,51,17,51,17,33,21,33,17,2,184,160,1,141,252,147,160,160,2,45,254,115, +3,22,4,107,252,65,172,250,234,9,129,246,127,4,106,172,252,66,0,0,0,0,1,255,236,254,0,2,184,7,129,0,11,0,0,1,17,33,53,33,53,33,53,33,17,51,17,2,24,253,212,2,44,253,212,2,44,160,254,0,3,190,172,172,172,3,191,246,127,0,2,255,236,254,0,3,88,7,129,0,7,0,11, +0,0,1,17,33,53,33,17,51,17,51,17,51,17,1,120,254,116,1,140,160,160,160,254,0,4,106,172,4,107,246,127,9,129,246,127,0,0,0,3,255,236,254,0,3,88,7,129,0,5,0,11,0,15,0,0,3,53,33,17,51,17,3,17,33,53,33,17,51,17,51,17,20,1,140,160,160,254,116,2,44,160,160, +3,22,172,3,191,251,149,250,234,3,190,172,251,150,9,129,246,127,0,0,2,255,236,254,0,4,229,3,194,0,7,0,11,0,0,1,17,33,53,33,21,33,17,1,53,33,21,2,24,253,212,4,249,253,211,253,52,4,249,254,0,3,190,172,172,252,66,5,22,172,172,0,1,255,236,254,0,4,229,3,22, +0,11,0,0,3,53,33,21,33,17,35,17,35,17,35,17,20,4,249,254,115,160,160,160,2,106,172,172,251,150,4,106,251,150,4,106,0,0,0,3,255,236,254,0,4,229,3,194,0,3,0,9,0,15,0,0,3,53,33,21,1,17,33,53,33,17,51,17,33,21,33,17,20,4,249,252,147,254,116,2,44,160,2,45, +254,115,3,22,172,172,250,234,3,190,172,251,150,4,106,172,252,66,0,2,255,236,1,190,4,229,7,129,0,3,0,11,0,0,3,53,33,21,1,53,33,17,51,17,33,21,20,4,249,251,7,2,44,160,2,45,1,190,172,172,1,88,172,3,191,252,65,172,0,0,0,1,255,236,2,106,4,229,7,129,0,11,0, +0,3,53,33,17,51,17,51,17,51,17,33,21,20,1,140,160,160,160,1,141,2,106,172,4,107,251,149,4,107,251,149,172,0,0,0,3,255,236,1,190,4,229,7,129,0,3,0,9,0,15,0,0,3,53,33,21,1,53,33,17,51,17,51,17,51,17,33,21,20,4,249,251,7,1,140,160,160,160,1,141,1,190,172, +172,1,88,172,3,191,251,149,4,107,252,65,172,0,0,0,1,255,236,254,0,4,229,7,129,0,19,0,0,1,17,33,53,33,53,33,53,33,17,51,17,33,21,33,21,33,21,33,17,2,24,253,212,2,44,253,212,2,44,160,2,45,253,211,2,45,253,211,254,0,3,190,172,172,172,3,191,252,65,172,172, +172,252,66,0,0,0,0,1,255,236,254,0,4,229,7,129,0,19,0,0,3,53,33,17,51,17,51,17,51,17,33,21,33,17,35,17,35,17,35,17,20,1,140,160,160,160,1,141,254,115,160,160,160,2,106,172,4,107,251,149,4,107,251,149,172,251,150,4,106,251,150,4,106,0,0,4,255,236,254, +0,4,229,7,129,0,5,0,11,0,17,0,23,0,0,1,17,33,21,33,17,33,17,33,53,33,17,1,53,33,17,51,17,51,17,51,17,33,21,2,184,2,45,254,115,254,32,254,116,2,44,253,212,1,140,160,160,160,1,141,254,0,4,106,172,252,66,3,190,172,251,150,5,22,172,3,191,251,149,4,107,252, +65,172,0,0,0,0,1,2,24,254,0,4,229,3,22,0,11,0,0,1,17,52,18,51,33,21,33,34,6,21,17,2,24,170,170,1,121,254,135,89,91,254,0,3,112,165,1,1,172,126,124,252,144,0,1,255,236,254,0,2,184,3,22,0,11,0,0,1,17,52,38,35,33,53,33,50,22,21,17,2,24,91,89,254,136,1,120, +168,172,254,0,3,112,126,124,172,254,168,252,144,0,0,1,255,236,2,106,2,184,7,129,0,11,0,0,3,53,33,50,54,53,17,51,17,20,6,35,20,1,120,89,91,160,172,168,2,106,172,126,124,3,113,252,143,168,254,0,0,0,0,1,2,24,2,106,4,229,7,129,0,11,0,0,1,33,34,38,53,17,51, +17,20,22,51,33,4,229,254,135,168,172,160,91,89,1,121,2,106,254,168,3,113,252,143,124,126,0,0,1,255,167,254,20,5,42,7,109,0,3,0,0,3,1,51,1,89,4,209,178,251,47,254,20,9,89,246,167,0,0,0,1,255,167,254,20,5,42,7,109,0,3,0,0,1,35,1,51,5,42,178,251,47,178, +254,20,9,89,0,1,255,167,254,20,5,42,7,109,0,11,0,0,1,35,9,1,35,9,1,51,9,1,51,1,5,42,178,253,240,253,241,178,2,105,253,151,178,2,15,2,16,178,253,152,254,20,4,0,252,0,4,172,4,173,252,0,4,0,251,83,0,0,0,1,255,236,2,106,2,104,3,22,0,3,0,0,3,53,33,21,20,2, +124,2,106,172,172,0,0,0,0,1,2,24,2,192,2,184,7,129,0,3,0,0,1,17,51,17,2,24,160,2,192,4,193,251,63,0,0,1,2,104,2,106,4,229,3,22,0,3,0,0,1,53,33,21,2,104,2,125,2,106,172,172,0,0,0,1,2,24,254,0,2,184,2,192,0,3,0,0,1,17,51,17,2,24,160,254,0,4,192,251,64, +0,0,1,255,236,2,19,2,104,3,108,0,3,0,0,3,17,5,17,20,2,124,2,20,1,88,1,254,168,0,1,1,200,2,192,3,8,7,129,0,3,0,0,1,17,33,17,1,200,1,64,2,192,4,193,251,63,0,1,2,104,2,20,4,229,3,108,0,3,0,0,1,17,33,17,2,104,2,125,2,20,1,88,254,168,0,1,1,200,254,0,3,8,2, +192,0,3,0,0,1,17,33,17,1,200,1,64,254,0,4,192,251,64,0,1,255,236,2,20,4,229,3,108,0,7,0,0,3,53,33,53,33,17,33,53,20,2,144,2,105,253,151,2,106,172,86,254,168,86,0,1,1,200,254,0,3,8,7,129,0,7,0,0,1,17,51,17,51,17,51,17,1,200,80,160,80,254,0,4,192,4,193, +251,63,251,64,0,0,0,0,1,255,236,2,20,4,229,3,108,0,7,0,0,3,17,33,21,33,21,33,21,20,2,144,2,105,253,151,2,20,1,88,86,172,86,0,1,1,200,254,0,3,8,7,129,0,7,0,0,1,17,35,17,33,17,35,17,2,24,80,1,64,80,254,0,4,192,4,193,251,63,251,64,0,0,255,255,255,236,2, +192,4,229,7,128,16,7,9,219,0,0,4,192,0,0,0,1,255,236,254,0,4,229,255,63,0,3,0,0,3,17,33,17,20,4,249,254,0,1,63,254,193,0,0,1,255,236,254,0,4,229,0,106,0,3,0,0,3,17,33,17,20,4,249,254,0,2,106,253,150,0,0,1,255,236,254,0,4,229,1,149,0,3,0,0,3,17,33,17, +20,4,249,254,0,3,149,252,107,0,0,1,255,236,254,0,4,229,2,192,0,3,0,0,3,17,33,17,20,4,249,254,0,4,192,251,64,0,0,1,255,236,254,0,4,229,3,236,0,3,0,0,3,17,33,17,20,4,249,254,0,5,236,250,20,0,0,1,255,236,254,0,4,229,5,23,0,3,0,0,3,17,33,17,20,4,249,254, +0,7,23,248,233,0,0,1,255,236,254,0,4,229,6,66,0,3,0,0,3,17,33,17,20,4,249,254,0,8,66,247,190,0,0,1,255,236,254,0,4,229,7,129,0,3,0,0,3,17,33,17,20,4,249,254,0,9,129,246,127,0,0,1,255,236,254,0,4,70,7,129,0,3,0,0,3,17,33,17,20,4,90,254,0,9,129,246,127, +0,0,1,255,236,254,0,3,166,7,129,0,3,0,0,3,17,33,17,20,3,186,254,0,9,129,246,127,0,0,1,255,236,254,0,3,7,7,129,0,3,0,0,3,17,33,17,20,3,27,254,0,9,129,246,127,0,0,1,255,236,254,0,2,104,7,129,0,3,0,0,3,17,33,17,20,2,124,254,0,9,129,246,127,0,0,1,255,236, +254,0,1,201,7,129,0,3,0,0,3,17,33,17,20,1,221,254,0,9,129,246,127,0,0,1,255,236,254,0,1,42,7,129,0,3,0,0,3,17,33,17,20,1,62,254,0,9,129,246,127,0,0,1,255,236,254,0,0,138,7,129,0,3,0,0,3,17,51,17,20,158,254,0,9,129,246,127,0,0,255,255,2,105,254,0,4,229, +7,129,16,7,9,227,2,125,0,0,0,0,0,16,0,0,254,20,4,56,7,109,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,35,0,39,0,43,0,47,0,51,0,55,0,59,0,63,0,0,1,53,51,21,33,53,51,21,19,53,51,21,33,53,51,21,1,53,51,21,33,53,51,21,19,53,51,21,33,53,51,21,1,53,51,21,33,53, +51,21,19,53,51,21,33,53,51,21,1,53,51,21,33,53,51,21,19,53,51,21,33,53,51,21,3,157,155,252,253,154,154,154,252,253,154,3,3,155,252,253,154,154,154,252,253,154,3,3,155,252,253,154,154,154,252,253,154,3,3,155,252,253,154,154,154,252,253,154,5,90,221,221, +221,221,1,54,221,221,221,221,247,132,221,221,221,221,1,54,221,221,221,221,1,55,221,221,221,221,1,53,222,222,222,222,1,55,222,222,222,222,1,54,221,221,221,221,0,30,0,0,254,20,4,209,7,108,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,35,0,39,0,43,0,47,0,51,0, +55,0,59,0,63,0,67,0,71,0,75,0,79,0,83,0,87,0,91,0,95,0,99,0,103,0,107,0,111,0,115,0,119,0,0,1,53,51,21,37,53,51,21,3,53,51,29,1,53,51,21,5,53,51,29,1,53,51,21,5,53,51,29,1,53,51,21,1,53,51,21,37,53,51,21,3,53,51,29,1,53,51,21,5,53,51,29,1,53,51,21,5, +53,51,29,1,53,51,21,1,53,51,21,37,53,51,21,3,53,51,29,1,53,51,21,5,53,51,29,1,53,51,21,5,53,51,29,1,53,51,21,1,53,51,21,37,53,51,21,5,53,51,21,37,53,51,21,5,53,51,21,37,53,51,21,4,4,205,254,101,206,206,206,205,254,101,206,205,254,101,206,205,253,152, +205,254,102,205,205,205,205,254,102,205,205,254,102,205,205,253,150,208,254,100,204,204,204,208,254,100,204,208,254,100,204,208,2,104,205,254,101,206,254,101,205,254,102,205,254,99,208,254,100,204,3,175,240,240,240,239,239,254,33,239,239,239,239,239, +239,239,239,240,240,240,239,239,239,239,239,239,5,155,240,240,240,239,239,254,33,239,239,239,239,239,239,239,239,240,240,240,239,239,239,239,239,239,5,155,240,240,240,239,239,254,33,239,239,239,239,239,239,239,239,240,240,240,239,239,239,239,239,239, +7,122,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,0,0,0,10,0,0,254,20,4,209,7,109,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,35,0,65,0,0,1,51,53,35,1,51,53,35,5,51,53,35,1,51,53,35,1,51,53,35,5,51,53,35,1,51,53,35,1,51,53,35,5,51, +53,35,3,33,17,35,53,35,21,33,53,35,21,33,17,51,53,35,17,51,53,35,17,51,53,35,17,51,53,33,21,51,2,104,154,154,254,204,154,154,2,104,155,155,254,204,154,154,254,204,154,154,2,104,155,155,254,204,154,154,254,204,154,154,2,104,155,155,154,1,207,154,155,254, +50,154,254,204,153,153,153,153,153,153,153,1,207,154,4,35,221,253,237,222,222,222,253,235,222,253,237,221,221,221,253,236,221,5,51,221,221,221,1,54,246,167,221,221,221,221,1,54,221,1,143,222,1,143,221,1,144,221,221,0,255,255,255,236,6,66,4,229,7,129, +16,7,9,216,0,0,8,66,0,0,255,255,4,70,254,0,4,228,7,129,16,7,9,230,4,90,0,0,0,0,0,1,255,236,254,0,2,105,2,192,0,3,0,0,3,17,33,17,20,2,125,254,0,4,192,251,64,0,255,255,2,105,254,0,4,230,2,192,16,7,9,237,2,125,0,0,0,0,255,255,255,236,2,192,2,105,7,128,16, +7,9,237,0,0,4,192,0,0,0,1,255,236,254,0,4,230,7,128,0,5,0,0,3,17,33,17,33,17,20,2,125,2,125,254,0,9,128,251,64,251,64,0,0,0,255,255,255,236,254,0,4,230,7,128,16,38,9,238,0,0,16,6,9,239,0,0,0,0,0,1,255,236,254,0,4,230,7,128,0,5,0,0,3,33,17,33,17,33,20, +4,250,253,131,253,131,7,128,251,64,251,64,0,0,0,0,1,255,236,254,0,4,230,7,128,0,5,0,0,1,17,33,17,33,17,4,230,253,131,253,131,7,128,246,128,4,192,4,192,0,0,255,255,2,105,2,192,4,230,7,128,16,7,9,237,2,125,4,192,0,0,255,255,255,236,254,0,4,230,7,128,16, +38,9,244,0,0,16,6,9,237,0,0,0,0,0,1,255,236,254,0,4,230,7,128,0,5,0,0,1,33,17,33,17,33,4,230,251,6,2,125,2,125,254,0,4,192,4,192,0,0,0,1,0,6,255,177,4,203,4,119,0,3,0,0,23,17,33,17,6,4,197,78,4,196,251,60,0,0,0,2,0,6,255,177,4,203,4,119,0,3,0,7,0,0,55, +33,17,33,3,17,33,17,120,3,225,252,31,114,4,197,36,3,224,251,174,4,196,251,60,0,0,0,0,2,0,6,255,177,4,203,4,119,0,11,0,23,0,0,19,20,51,33,50,53,17,52,35,33,34,21,3,17,16,41,1,32,25,1,16,41,1,32,120,228,2,25,228,228,253,231,228,114,1,86,2,25,1,86,254,170, +253,231,254,170,1,8,228,228,2,24,228,228,253,232,2,24,1,86,254,170,253,232,254,170,0,0,255,255,0,6,255,177,4,203,4,119,16,38,10,1,0,0,16,6,9,248,0,0,0,0,0,6,0,6,255,177,4,203,4,119,0,3,0,7,0,11,0,15,0,19,0,23,0,0,23,17,33,17,37,33,53,33,53,33,53,33,53, +33,53,33,53,33,53,33,53,33,53,33,6,4,197,251,173,3,225,252,31,3,225,252,31,3,225,252,31,3,225,252,31,3,225,252,31,78,4,196,251,60,114,110,114,106,114,107,114,107,114,106,0,6,0,6,255,177,4,203,4,119,0,3,0,7,0,11,0,15,0,19,0,23,0,0,23,17,33,17,39,51,17, +35,3,51,17,35,3,51,17,35,3,51,17,35,3,51,17,35,6,4,197,225,110,110,220,106,106,220,106,106,222,108,108,220,106,106,78,4,196,251,60,114,3,224,252,32,3,224,252,32,3,224,252,32,3,224,252,32,3,224,0,0,0,26,0,6,255,177,4,203,4,119,0,3,0,7,0,11,0,15,0,19,0, +23,0,27,0,31,0,35,0,39,0,43,0,47,0,51,0,55,0,59,0,63,0,67,0,71,0,75,0,79,0,83,0,87,0,91,0,95,0,99,0,103,0,0,19,51,53,35,17,51,53,35,17,51,53,35,17,51,53,35,17,51,53,35,19,51,53,35,17,51,53,35,17,51,53,35,17,51,53,35,17,51,53,35,19,51,53,35,17,51,53,35, +17,51,53,35,17,51,53,35,17,51,53,35,19,51,53,35,17,51,53,35,17,51,53,35,17,51,53,35,17,51,53,35,19,51,53,35,17,51,53,35,17,51,53,35,17,51,53,35,17,51,53,35,5,17,33,17,120,106,106,106,106,106,106,106,106,106,106,220,108,108,108,108,108,108,108,108,108, +108,222,106,106,106,106,106,106,106,106,106,106,220,106,106,106,106,106,106,106,106,106,106,220,110,110,110,110,110,110,110,110,110,110,252,28,4,197,3,154,106,254,185,107,254,184,107,254,185,106,254,182,110,3,8,106,254,185,107,254,184,107,254,185,106, +254,182,110,3,8,106,254,185,107,254,184,107,254,185,106,254,182,110,3,8,106,254,185,107,254,184,107,254,185,106,254,182,110,3,8,106,254,185,107,254,184,107,254,185,106,254,182,110,224,4,196,251,60,0,0,8,0,6,255,177,4,203,4,119,0,3,0,7,0,11,0,17,0,21, +0,25,0,28,0,31,0,0,23,17,33,17,1,21,1,51,1,21,1,55,1,21,1,51,53,1,51,1,53,1,51,1,53,1,51,23,53,1,21,51,6,4,197,251,173,1,52,138,254,66,2,96,149,253,11,3,151,74,252,108,161,2,243,253,164,162,1,186,254,208,162,142,252,31,146,78,4,196,251,60,2,48,139,254, +205,2,245,150,253,160,1,3,224,74,252,106,76,3,148,253,14,151,2,91,254,70,139,1,47,142,142,252,178,146,0,0,0,8,0,6,255,177,4,203,4,119,0,3,0,7,0,11,0,17,0,21,0,25,0,28,0,31,0,0,23,17,33,17,37,51,1,53,1,23,1,53,1,51,1,53,35,1,53,1,35,1,53,1,35,1,53,55, +35,1,51,53,6,4,197,253,208,138,1,52,253,11,149,2,96,252,31,74,3,151,77,252,108,2,243,151,253,164,1,186,138,254,208,142,142,3,79,146,78,4,196,251,60,114,1,51,139,254,66,1,2,96,150,253,11,3,150,74,252,108,162,2,242,253,165,161,1,186,254,209,161,142,252, +32,146,0,0,0,0,26,0,6,255,177,4,203,4,119,0,4,0,9,0,14,0,19,0,23,0,28,0,33,0,37,0,41,0,45,0,50,0,55,0,59,0,63,0,67,0,71,0,75,0,80,0,84,0,88,0,92,0,97,0,102,0,106,0,111,0,115,0,0,37,23,51,53,39,1,23,55,39,35,17,23,55,39,7,1,23,55,39,35,7,23,55,39,3,23, +55,39,7,1,23,55,39,35,7,23,55,39,7,23,55,39,7,23,55,39,3,51,55,39,7,1,23,55,53,35,7,23,55,39,7,23,55,39,7,23,55,39,7,23,55,39,7,23,55,39,1,23,55,53,39,7,23,55,39,7,23,55,39,7,23,55,39,7,23,51,55,39,37,23,55,53,39,7,23,55,39,7,23,51,55,39,5,17,33,17,3, +235,36,74,35,252,66,34,76,33,77,28,76,70,34,1,15,69,76,27,85,189,69,76,70,190,35,69,75,29,2,65,76,69,33,85,183,75,76,76,231,75,76,76,231,76,75,76,184,74,36,75,35,3,116,75,34,77,182,75,69,75,226,76,75,75,232,75,76,76,230,75,75,76,224,75,69,75,2,193,74, +29,34,226,75,76,75,232,75,76,76,230,74,76,76,224,36,78,30,75,2,36,69,35,29,231,69,75,69,231,30,78,36,69,253,2,4,197,72,36,76,35,3,39,34,76,32,254,127,29,76,69,34,1,14,69,76,26,189,69,76,69,253,196,34,69,75,28,2,65,76,69,33,183,75,75,76,232,75,75,76,231, +76,75,76,253,195,36,75,35,3,116,76,34,74,182,76,69,76,226,75,75,76,232,75,75,75,230,76,75,75,224,75,69,75,1,137,76,29,82,34,226,75,76,75,232,75,76,74,230,76,76,74,224,36,30,75,237,69,34,82,28,231,69,75,69,231,30,36,69,219,4,196,251,60,0,0,1,0,219,0,135, +3,245,3,161,0,3,0,0,55,17,33,17,219,3,26,135,3,26,252,230,0,0,0,2,0,219,0,135,3,245,3,161,0,3,0,7,0,0,37,33,17,33,3,17,33,17,1,77,2,54,253,202,114,3,26,249,2,54,253,88,3,26,252,230,0,0,0,1,0,6,0,240,4,203,3,56,0,3,0,0,37,33,17,33,4,203,251,59,4,197,240, +2,72,0,0,2,0,6,0,240,4,203,3,56,0,3,0,7,0,0,1,17,33,17,5,33,17,33,4,89,252,31,4,83,251,59,4,197,1,98,1,100,254,156,114,2,72,0,0,1,1,68,255,177,3,141,4,119,0,3,0,0,5,17,33,17,1,68,2,72,78,4,196,251,60,0,0,2,1,68,255,177,3,141,4,119,0,3,0,7,0,0,37,33,17, +33,3,17,33,17,1,182,1,100,254,156,114,2,72,36,3,224,251,174,4,196,251,60,0,0,0,1,0,6,0,240,4,203,3,56,0,3,0,0,37,33,1,33,3,151,252,111,1,52,3,145,240,2,72,0,0,0,0,2,0,6,0,240,4,203,3,56,0,3,0,7,0,0,1,19,33,3,5,33,1,33,3,97,188,253,83,188,2,227,252,111, +1,52,3,145,1,98,1,100,254,156,114,2,72,0,0,1,0,6,255,177,4,203,4,119,0,2,0,0,23,9,1,6,2,98,2,99,78,4,196,251,60,0,0,2,0,6,255,177,4,203,4,119,0,2,0,5,0,0,55,33,9,3,177,3,111,254,72,253,158,2,98,2,99,36,3,110,252,32,4,196,251,60,0,1,0,219,0,135,3,245, +3,161,0,2,0,0,55,9,1,219,1,141,1,141,135,3,26,252,230,0,0,2,0,219,0,135,3,245,3,161,0,2,0,5,0,0,37,33,3,9,2,1,134,1,196,226,254,115,1,141,1,141,249,1,196,253,202,3,26,252,230,0,0,0,0,1,0,6,255,177,4,203,4,119,0,2,0,0,23,17,1,6,4,197,78,4,196,253,158, +0,0,0,0,2,0,6,255,177,4,203,4,119,0,2,0,5,0,0,55,9,1,3,17,1,120,3,111,252,145,114,4,197,92,1,184,1,184,251,230,4,196,253,158,0,0,0,0,1,0,219,0,135,3,245,3,161,0,2,0,0,55,17,1,219,3,26,135,3,26,254,115,0,0,0,0,2,0,219,0,135,3,245,3,161,0,2,0,5,0,0,1,45, +1,3,17,1,1,77,1,196,254,60,114,3,26,1,50,226,226,253,145,3,26,254,115,0,0,0,0,1,0,6,0,135,4,203,3,161,0,2,0,0,55,17,1,6,4,197,135,3,26,254,115,0,0,0,0,2,0,6,0,135,4,203,3,161,0,2,0,5,0,0,19,45,1,3,17,1,120,3,54,252,202,114,4,197,1,50,226,226,253,145, +3,26,254,115,0,1,0,6,255,177,4,203,4,119,0,2,0,0,5,1,33,2,104,253,158,4,197,78,4,196,0,0,0,2,0,6,255,177,4,203,4,119,0,2,0,5,0,0,37,1,33,9,1,33,2,104,1,149,252,215,1,148,253,158,4,197,205,3,40,251,189,4,196,0,0,0,0,1,0,219,0,135,3,245,3,161,0,2,0,0,37, +1,33,2,104,254,115,3,26,135,3,26,0,0,0,2,0,219,0,135,3,245,3,161,0,2,0,5,0,0,1,19,33,19,1,33,2,104,226,254,60,226,254,115,3,26,1,107,1,196,253,88,3,26,0,1,0,6,255,177,4,203,4,119,0,2,0,0,19,1,17,6,4,197,2,20,2,98,251,60,0,0,0,2,0,6,255,177,4,203,4,119, +0,2,0,5,0,0,19,1,17,9,1,17,234,3,111,251,173,4,197,2,20,254,72,3,112,254,72,2,98,251,60,0,0,0,0,1,0,219,0,135,3,245,3,161,0,2,0,0,19,1,17,219,3,26,2,20,1,141,252,230,0,0,0,2,0,219,0,135,3,245,3,161,0,2,0,5,0,0,1,5,17,5,1,17,1,191,1,196,253,88,3,26,2, +20,226,1,196,226,1,141,252,230,0,1,0,6,0,135,4,203,3,161,0,2,0,0,19,1,17,6,4,197,2,20,1,141,252,230,0,0,0,2,0,6,0,135,4,203,3,161,0,2,0,5,0,0,1,5,17,5,1,17,1,35,3,54,251,173,4,197,2,20,226,1,196,226,1,141,252,230,0,1,0,6,255,177,4,203,4,119,0,3,0,0,19, +9,2,6,2,98,2,99,253,157,2,20,2,98,253,158,253,158,0,2,0,6,255,177,4,203,4,119,0,3,0,7,0,0,19,9,6,195,1,165,1,166,254,90,253,158,2,98,2,99,253,157,2,20,254,90,1,166,1,166,254,90,2,98,253,158,253,158,0,0,0,3,0,6,255,177,4,203,4,119,0,3,0,7,0,11,0,0,19, +9,10,250,1,110,1,110,254,146,254,54,1,202,1,203,254,53,253,158,2,98,2,99,253,157,2,20,1,110,254,146,254,146,1,110,254,54,1,202,1,202,254,54,2,98,253,158,253,158,0,3,0,6,255,172,4,203,4,124,0,13,0,27,0,41,0,0,18,16,55,54,51,50,23,22,16,7,6,35,34,39,0, +16,23,22,51,50,55,54,16,39,38,35,34,7,0,16,37,54,51,50,23,4,16,5,6,35,34,39,220,198,99,99,99,99,199,199,99,99,99,99,254,222,244,122,122,122,122,245,245,122,122,122,122,254,146,1,49,152,153,152,153,1,50,254,206,153,152,153,152,1,47,1,202,114,57,57,114, +254,54,114,57,57,2,113,253,204,140,71,71,141,2,50,141,71,71,252,250,2,192,176,88,88,176,253,64,176,88,88,0,2,0,117,254,35,4,92,6,117,0,3,0,7,0,34,64,17,2,6,0,8,4,6,8,6,4,3,2,1,0,6,5,7,8,16,212,204,23,57,49,0,16,212,204,17,57,18,57,48,9,7,2,104,254,127, +1,129,1,129,254,127,1,244,254,12,254,13,5,129,252,207,252,199,3,57,4,37,251,219,251,211,4,45,0,2,0,6,255,172,4,203,4,124,0,13,0,27,0,0,18,16,23,22,51,50,55,54,16,39,38,35,34,7,0,16,37,54,51,50,23,4,16,5,6,35,34,39,128,244,122,122,122,122,245,245,122, +122,122,122,254,146,1,49,152,153,152,153,1,50,254,206,153,152,153,152,3,46,253,204,140,71,71,141,2,50,141,71,71,252,250,2,192,176,88,88,176,253,64,176,88,88,0,0,0,8,0,6,255,172,4,203,4,124,0,9,0,19,0,29,0,39,0,47,0,55,0,63,0,71,0,0,55,22,23,22,23,7,38, +39,38,39,5,54,55,54,55,23,6,7,6,7,19,38,39,38,39,55,22,23,22,23,37,6,7,6,7,39,54,55,54,55,19,22,50,55,23,6,34,39,1,54,52,39,55,22,20,7,1,38,34,7,39,54,50,23,1,6,20,23,7,38,52,55,212,34,46,36,44,61,55,45,58,42,2,237,44,36,41,39,101,49,51,45,55,99,34,46, +36,44,61,55,45,58,42,253,19,44,36,46,34,101,42,58,45,55,185,60,120,60,30,75,150,75,2,114,13,13,119,16,16,254,37,60,120,60,30,75,150,75,253,143,13,13,119,16,16,250,47,38,30,25,106,32,37,48,58,69,25,30,34,51,70,65,42,37,32,3,42,47,38,30,25,106,32,37,48, +58,69,25,30,38,47,71,58,48,37,32,252,20,17,17,119,21,21,1,219,57,126,57,30,71,158,71,2,114,17,17,119,21,21,254,37,57,126,57,30,71,158,71,0,0,0,6,0,6,255,172,4,203,4,124,0,13,0,23,0,27,0,37,0,47,0,51,0,0,54,16,37,54,51,50,23,4,16,5,6,35,34,39,19,17,22, +23,22,23,17,6,7,6,7,6,16,23,1,17,22,51,50,55,17,38,35,34,23,17,54,55,54,55,17,38,39,38,23,17,54,16,6,1,49,152,153,152,153,1,50,254,206,153,152,153,152,29,15,17,38,38,38,38,17,129,98,98,1,80,27,27,26,26,26,26,27,193,39,39,14,14,14,14,39,181,103,180,2, +192,176,88,88,176,253,64,176,88,88,3,163,252,218,10,9,22,15,3,150,15,22,9,113,122,254,156,122,3,21,252,46,4,3,3,212,3,33,252,104,15,23,8,9,3,42,9,8,23,139,253,156,124,1,108,0,0,0,4,0,6,255,172,4,203,4,124,0,13,0,27,0,41,0,55,0,0,0,20,23,22,51,50,55,54, +52,39,38,35,34,7,2,16,55,54,51,50,23,22,16,7,6,35,34,39,0,16,23,22,51,50,55,54,16,39,38,35,34,7,0,16,37,54,51,50,23,4,16,5,6,35,34,39,1,226,67,34,33,34,33,68,68,33,34,33,34,177,122,61,61,61,61,123,123,61,61,61,61,254,146,244,122,122,122,122,245,245,122, +122,122,122,254,146,1,49,152,153,152,153,1,50,254,206,153,152,153,152,2,97,154,39,20,20,39,154,39,20,20,254,255,1,26,70,35,35,70,254,230,70,35,35,1,237,253,204,140,71,71,141,2,50,141,71,71,252,250,2,192,176,88,88,176,253,64,176,88,88,0,1,0,6,255,172, +4,203,4,124,0,13,0,0,54,16,37,54,51,50,23,4,16,5,6,35,34,39,6,1,49,152,153,152,153,1,50,254,206,153,152,153,152,180,2,192,176,88,88,176,253,64,176,88,88,0,0,2,0,6,255,172,4,203,4,124,0,7,0,21,0,0,37,50,55,54,16,39,38,35,0,16,37,54,51,50,23,4,16,5,6,35, +34,39,2,104,122,122,245,245,122,122,253,158,1,49,152,153,152,153,1,50,254,206,153,152,153,152,39,71,141,2,50,141,71,252,179,2,192,176,88,88,176,253,64,176,88,88,0,0,0,2,0,6,255,172,4,203,4,124,0,7,0,21,0,0,1,34,7,6,16,23,22,51,36,16,37,54,51,50,23,4, +16,5,6,35,34,39,2,104,122,122,244,244,122,122,253,158,1,49,152,153,152,153,1,50,254,206,153,152,153,152,4,1,71,140,253,204,140,71,141,2,192,176,88,88,176,253,64,176,88,88,0,0,0,2,0,6,255,172,4,203,4,124,0,8,0,22,0,0,1,16,39,38,35,34,7,6,17,2,16,37,54, +51,50,23,4,16,5,6,35,34,39,4,81,245,122,122,122,122,244,122,1,49,152,153,152,153,1,50,254,206,153,152,153,152,2,20,1,25,141,71,71,140,254,230,254,160,2,192,176,88,88,176,253,64,176,88,88,0,0,0,0,2,0,6,255,172,4,203,4,124,0,8,0,22,0,0,19,16,23,22,51,50, +55,54,17,0,16,37,54,51,50,23,4,16,5,6,35,34,39,128,244,122,122,122,122,245,251,181,1,49,152,153,152,153,1,50,254,206,153,152,153,152,2,20,254,230,140,71,71,141,1,25,254,160,2,192,176,88,88,176,253,64,176,88,88,0,0,0,0,2,0,6,255,172,4,203,4,124,0,12,0, +26,0,0,1,34,7,6,16,23,22,51,50,55,54,17,33,0,16,37,54,51,50,23,4,16,5,6,35,34,39,2,104,122,122,244,244,122,122,122,122,245,254,23,253,158,1,49,152,153,152,153,1,50,254,206,153,152,153,152,4,1,71,140,253,204,140,71,71,141,1,25,254,160,2,192,176,88,88, +176,253,64,176,88,88,0,0,0,0,2,0,6,255,172,4,203,4,124,0,5,0,19,0,0,1,34,7,6,17,33,0,16,37,54,51,50,23,4,16,5,6,35,34,39,2,104,122,122,244,1,232,253,158,1,49,152,153,152,153,1,50,254,206,153,152,153,152,4,1,71,140,254,230,254,160,2,192,176,88,88,176, +253,64,176,88,88,0,0,0,1,1,55,255,172,3,154,4,124,0,7,0,0,5,34,39,36,16,37,54,51,3,154,154,152,254,208,1,48,152,154,84,88,176,2,192,176,88,0,0,1,1,55,255,172,3,154,4,124,0,7,0,0,1,50,23,4,16,5,6,35,1,56,150,154,1,50,254,206,154,150,4,124,88,176,253,64, +174,90,0,2,255,236,255,236,4,229,6,40,0,11,0,15,0,0,1,20,22,51,50,54,53,52,38,35,34,6,1,17,33,17,1,63,171,124,125,174,173,124,125,172,254,173,4,249,2,250,126,171,173,124,123,172,171,252,118,6,60,249,196,0,0,0,0,3,255,236,254,0,4,229,6,40,0,13,0,27,0, +31,0,0,54,16,55,54,51,50,23,22,16,7,6,35,34,39,0,16,5,22,51,50,55,36,16,37,38,35,34,7,1,17,33,17,128,244,122,122,122,122,245,245,122,122,122,122,254,146,1,49,152,153,152,153,1,50,254,206,153,152,153,152,254,181,4,249,250,2,52,140,71,71,141,253,206,141, +71,71,3,6,253,64,176,88,88,176,2,192,176,88,88,249,220,8,40,247,216,0,0,0,0,2,255,236,2,20,4,229,6,40,0,12,0,21,0,0,3,17,33,17,35,16,37,38,35,34,7,4,17,41,1,16,55,54,51,50,23,22,20,4,249,26,254,206,153,152,153,152,254,207,4,75,252,47,244,122,122,122, +122,245,2,20,4,20,251,236,1,96,176,88,88,176,254,160,1,25,141,71,71,141,0,2,255,236,254,0,4,229,2,20,0,12,0,21,0,0,3,17,51,16,5,22,51,50,55,36,17,51,17,1,33,16,7,6,35,34,39,38,20,26,1,49,152,153,152,153,1,50,26,251,155,3,209,245,122,122,122,122,244,254, +0,4,20,254,160,176,88,88,176,1,96,251,236,4,20,254,231,141,71,71,141,0,0,0,0,1,1,55,2,20,3,154,4,124,0,9,0,0,1,16,37,54,51,23,34,7,6,17,1,55,1,49,152,153,1,123,121,244,2,20,1,96,176,88,123,71,140,254,230,0,0,0,0,1,1,55,2,20,3,154,4,124,0,9,0,0,1,50,23, +4,17,35,16,39,38,35,1,56,150,154,1,50,123,244,123,120,4,124,88,176,254,160,1,25,141,71,0,1,1,55,255,172,3,154,2,20,0,9,0,0,5,53,50,55,54,17,51,16,5,6,1,56,120,123,244,123,254,206,154,84,123,71,141,1,25,254,160,174,90,0,0,1,1,55,255,172,3,154,2,20,0,9, +0,0,5,34,39,36,17,51,16,23,22,51,3,153,153,152,254,207,123,244,121,123,84,88,176,1,96,254,230,140,71,0,0,1,0,6,2,20,4,203,4,124,0,17,0,0,19,16,37,54,51,50,23,4,17,35,16,39,38,35,34,7,6,17,6,1,49,152,153,152,153,1,50,122,245,122,122,122,122,244,2,20,1, +96,176,88,88,176,254,160,1,25,141,71,71,140,254,230,0,0,0,1,0,6,255,172,4,203,2,20,0,18,0,0,19,48,51,16,23,22,51,50,55,54,17,51,16,5,6,35,34,39,36,6,122,244,122,122,122,122,245,122,254,206,153,152,153,152,254,207,2,20,254,230,140,71,71,141,1,25,254,160, +176,88,88,176,0,0,0,1,0,6,255,177,4,203,4,119,0,2,0,0,23,1,17,6,4,197,78,4,196,251,60,0,0,0,0,1,0,6,255,177,4,203,4,119,0,2,0,0,23,17,1,6,4,197,78,4,196,251,60,0,0,0,0,1,0,6,255,177,4,203,4,119,0,2,0,0,23,17,33,6,4,197,78,4,196,0,0,1,0,6,255,177,4,203, +4,119,0,2,0,0,19,33,17,6,4,197,4,118,251,60,0,2,1,63,1,209,3,145,4,33,0,11,0,23,0,0,1,20,22,51,50,54,53,52,38,35,34,6,7,52,54,51,50,22,21,20,6,35,34,38,1,122,137,99,100,140,139,99,100,138,59,172,125,124,173,174,125,124,171,2,250,101,137,139,99,98,138, +137,99,124,171,172,123,124,173,171,0,2,0,6,255,177,4,203,4,119,0,3,0,7,0,0,37,33,17,33,1,17,33,17,2,104,1,240,254,16,253,158,4,197,36,3,224,251,174,4,196,251,60,0,0,2,0,6,255,177,4,203,4,119,0,3,0,7,0,0,55,33,17,33,3,17,33,17,120,1,240,254,16,114,4,197, +36,3,224,251,174,4,196,251,60,0,0,0,0,2,0,6,255,177,4,203,4,119,0,2,0,6,0,0,55,33,17,1,17,33,17,120,3,224,251,174,4,197,36,3,224,251,174,4,196,251,60,0,0,2,0,6,255,177,4,203,4,119,0,2,0,6,0,0,55,1,33,3,17,33,17,120,3,225,252,31,114,4,197,36,3,224,251, +174,4,196,251,60,0,3,0,6,255,177,4,203,4,119,0,3,0,7,0,11,0,0,37,33,17,33,1,33,17,33,3,17,33,17,2,161,1,183,254,73,253,215,1,183,254,73,114,4,197,36,3,224,252,32,3,224,251,174,4,196,251,60,0,0,0,3,0,6,255,177,4,203,4,119,0,11,0,14,0,17,0,0,1,52,54,51, +50,22,21,20,6,35,34,38,1,33,9,3,1,226,78,56,56,78,79,56,56,77,254,207,3,111,254,72,253,158,2,98,2,99,1,106,56,77,77,56,55,78,77,254,242,3,110,252,32,4,196,251,60,0,0,2,0,6,255,177,4,203,4,119,0,2,0,5,0,0,37,33,9,3,2,104,1,184,254,72,253,158,2,98,2,99, +36,3,110,252,32,4,196,251,60,0,0,0,0,2,0,6,255,177,4,203,4,119,0,2,0,5,0,0,55,33,17,9,2,177,1,183,253,158,2,98,2,99,36,3,110,252,32,4,196,251,60,0,0,2,255,236,255,146,4,229,4,150,0,13,0,27,0,0,18,16,5,22,51,50,55,36,16,39,38,35,34,7,0,16,37,54,51,50, +23,4,16,5,6,35,34,39,107,0,255,126,128,127,128,0,255,255,128,127,128,126,254,130,1,62,158,160,159,159,1,63,254,193,159,159,160,158,3,58,253,180,147,73,73,147,2,76,147,73,73,252,216,2,222,184,91,91,184,253,34,184,91,91,0,3,0,6,255,177,4,203,4,119,0,3, +0,7,0,13,0,0,23,17,33,17,1,33,17,33,17,33,17,33,17,33,6,4,197,251,173,1,183,254,73,3,224,254,73,253,215,78,4,196,251,60,2,154,1,184,252,32,3,224,253,214,0,0,0,3,0,6,255,177,4,203,4,119,0,3,0,7,0,13,0,0,23,17,33,17,37,33,17,33,53,33,17,33,17,33,6,4,197, +251,173,1,183,254,73,2,41,1,183,252,32,78,4,196,251,60,114,1,182,114,253,216,3,224,0,3,0,6,255,177,4,203,4,119,0,3,0,7,0,13,0,0,23,17,33,17,37,33,17,33,1,33,17,33,17,33,6,4,197,253,214,1,183,254,73,253,215,1,183,2,41,252,32,78,4,196,251,60,114,1,182, +254,74,2,40,1,184,0,0,3,0,6,255,177,4,203,4,119,0,3,0,7,0,13,0,0,23,17,33,17,1,33,17,33,1,33,17,33,17,33,6,4,197,253,214,1,183,254,73,253,215,3,224,253,215,254,73,78,4,196,251,60,2,154,1,184,252,32,1,182,2,42,0,3,0,6,255,172,4,203,4,124,0,13,0,19,0,32, +0,0,54,16,37,54,51,50,23,4,16,5,6,35,34,39,19,6,7,6,7,33,5,22,23,22,51,50,55,54,16,39,38,39,17,6,1,49,152,153,152,153,1,50,254,206,153,152,153,152,248,94,93,219,22,1,172,254,84,23,218,122,122,122,122,245,245,94,93,180,2,192,176,88,88,176,253,64,176,88, +88,3,249,13,54,126,240,114,238,126,71,71,141,2,50,141,54,13,253,221,0,3,0,6,255,172,4,203,4,124,0,13,0,26,0,32,0,0,54,16,37,54,51,50,23,4,16,5,6,35,34,39,37,54,55,54,16,39,38,35,34,7,6,7,33,5,22,23,22,23,17,6,1,49,152,153,152,153,1,50,254,206,153,152, +153,152,1,106,93,94,245,245,122,122,122,122,219,22,2,30,253,226,23,218,93,94,180,2,192,176,88,88,176,253,64,176,88,88,39,13,54,141,2,50,141,71,71,126,240,114,238,126,54,13,1,175,0,3,0,6,255,172,4,203,4,124,0,13,0,26,0,32,0,0,54,16,37,54,51,50,23,4,16, +5,6,35,34,39,2,16,23,22,23,17,33,38,39,38,35,34,7,1,54,55,54,55,33,6,1,49,152,153,152,153,1,50,254,206,153,152,153,152,183,244,93,94,2,31,22,220,122,122,122,122,1,45,93,94,219,23,254,83,180,2,192,176,88,88,176,253,64,176,88,88,3,41,253,206,141,54,13, +2,33,240,126,71,71,252,113,13,54,126,238,0,0,0,0,3,0,6,255,172,4,203,4,124,0,13,0,26,0,32,0,0,54,16,37,54,51,50,23,4,16,5,6,35,34,39,2,16,23,22,51,50,55,54,55,33,17,6,7,1,38,39,38,39,17,6,1,49,152,153,152,153,1,50,254,206,153,152,153,152,183,244,122, +122,122,122,219,23,253,225,94,93,2,218,22,220,94,93,180,2,192,176,88,88,176,253,64,176,88,88,3,41,253,206,141,71,71,126,238,2,35,13,54,254,146,240,126,54,13,254,79,0,0,0,0,2,0,6,255,177,4,203,4,119,0,2,0,5,0,0,55,1,33,3,17,33,120,3,54,252,202,114,4,197, +206,3,54,251,174,4,196,0,0,0,0,2,0,6,255,177,4,203,4,119,0,2,0,5,0,0,9,1,17,37,33,17,1,35,3,54,251,173,4,197,4,4,252,202,3,54,114,251,60,0,0,2,0,6,255,177,4,203,4,119,0,2,0,5,0,0,55,33,1,3,17,1,120,3,54,252,202,114,4,197,36,3,54,252,88,4,196,251,60,0, +0,2,0,97,0,13,4,111,4,27,0,3,0,7,0,0,55,33,17,33,3,17,33,17,211,3,42,252,214,114,4,14,127,3,42,252,100,4,14,251,242,0,0,0,0,1,0,97,0,13,4,111,4,27,0,3,0,0,55,17,33,17,97,4,14,13,4,14,251,242,0,0,0,2,0,175,0,91,4,33,3,205,0,3,0,7,0,0,37,33,17,33,3,17, +33,17,1,33,2,142,253,114,114,3,114,205,2,142,253,0,3,114,252,142,0,0,0,1,0,175,0,91,4,33,3,205,0,3,0,0,55,17,33,17,175,3,114,91,3,114,252,142,0,0,0,2,0,6,255,177,4,203,4,119,0,2,0,5,0,0,37,33,17,9,1,17,1,35,3,54,251,173,4,197,36,3,54,252,88,4,196,251, +60,0,0,9,0,34,0,164,4,175,5,49,0,7,0,12,0,19,0,34,0,42,0,50,0,58,0,65,0,73,0,0,1,51,23,17,7,35,39,17,5,23,21,7,39,37,23,7,35,38,39,53,5,50,31,1,20,7,6,35,34,39,38,53,52,55,54,5,33,23,21,7,33,39,53,37,33,23,21,7,33,39,53,7,51,22,23,21,7,39,53,37,51,23, +21,7,39,53,37,51,23,17,7,35,39,17,2,78,60,4,4,60,5,1,186,46,194,48,253,167,196,47,2,157,35,1,181,163,69,10,148,55,36,137,76,28,143,52,253,228,1,8,5,5,254,248,5,3,122,1,14,5,5,254,242,4,56,3,104,89,47,194,254,54,2,46,192,48,1,165,60,4,4,60,5,5,49,5,254, +239,4,4,1,17,121,49,2,198,49,186,199,50,156,43,3,141,176,75,147,79,17,130,49,72,141,80,22,215,5,61,5,5,61,5,5,61,5,5,61,218,102,94,2,49,198,3,32,46,3,198,49,3,92,4,254,239,5,5,1,17,0,0,0,1,0,50,0,8,4,159,1,209,0,34,0,0,1,51,50,31,1,54,51,22,21,20,7,22, +29,1,6,35,33,53,50,55,54,59,1,39,52,63,1,23,39,52,63,1,50,23,54,3,0,13,134,72,12,24,34,83,21,63,11,49,251,209,35,82,29,32,20,7,98,24,26,3,125,41,30,28,74,1,209,143,53,22,17,67,30,32,14,44,16,63,6,107,24,30,67,30,2,2,7,91,55,5,27,62,0,0,0,1,0,34,0,6,4, +175,4,45,0,63,0,0,1,51,23,21,51,32,19,22,29,1,35,38,39,38,43,1,34,7,21,20,7,39,38,35,17,20,15,1,34,47,1,53,55,51,23,21,22,59,1,50,63,1,17,34,7,6,35,39,53,55,35,38,39,35,34,15,1,35,53,54,55,54,51,53,2,97,41,4,2,1,56,199,31,1,16,14,24,41,31,107,79,6,24, +107,97,75,21,65,26,2,4,31,4,7,45,7,39,14,4,150,61,12,10,5,5,3,47,141,47,71,24,14,2,41,137,170,221,4,44,4,89,254,166,61,9,6,11,33,17,72,36,11,1,47,43,254,25,72,17,1,68,20,18,5,5,8,72,41,29,1,225,43,41,4,9,36,46,19,44,12,1,102,155,159,89,0,0,15,0,89,255, +250,4,120,5,171,0,9,0,17,0,25,0,33,0,61,0,90,0,133,0,177,0,220,1,8,1,16,1,24,1,32,1,76,1,120,0,0,1,22,55,51,6,7,38,39,51,22,55,38,39,54,55,22,23,6,5,38,39,54,55,22,23,6,3,38,39,54,55,22,23,6,39,6,21,20,22,51,50,54,53,52,39,38,39,22,55,54,53,52,38,35, +34,6,21,20,23,22,51,6,19,54,55,50,31,1,22,20,7,6,7,22,23,22,21,20,4,32,36,53,52,55,54,55,38,39,38,52,55,1,23,39,38,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23,22,35,34,63,1,7,6,35,34,53,52,63,1,39,38,53,52,51,50,3,23,39,38,51,50,15,1,55, +54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23,22,35,34,63,1,7,6,35,34,53,52,63,1,39,38,53,52,51,50,1,23,39,38,51,50,15,1,55,54,51,50,21,20,15,1,23,22,20,35,34,47,1,23,22,35,34,63,1,7,6,35,34,53,52,63,1,39,38,53,52,51,48,31,1,39,38,51,50,15,1,55,54,51, +50,21,20,15,1,23,22,21,20,35,34,47,1,23,22,35,34,63,1,7,6,35,34,53,52,63,1,39,38,53,52,51,50,1,38,53,52,51,50,21,20,5,38,53,54,51,50,21,20,55,38,53,52,51,50,21,20,19,23,39,38,51,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23,22,35,34,63,1,7, +6,35,34,53,52,63,1,39,38,53,52,51,50,1,23,39,38,51,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23,22,35,34,63,1,7,6,35,34,53,52,63,1,39,38,53,52,51,50,2,80,79,28,25,5,128,126,9,24,41,185,42,1,3,43,39,3,3,254,235,41,3,3,43,40,3,3,64,38,2,3,39, +36,2,2,202,124,247,175,174,248,124,101,139,63,47,65,125,93,92,138,66,45,55,144,21,26,147,132,49,2,83,76,20,24,111,87,142,254,228,254,106,254,227,143,92,118,21,19,76,76,2,114,37,6,1,28,1,6,37,4,4,14,7,44,42,7,12,6,2,35,4,1,14,14,1,5,36,2,5,13,8,41,42, +8,14,3,110,36,5,1,13,16,2,6,37,4,4,13,7,43,41,8,12,6,2,36,5,1,15,13,1,4,35,2,5,14,8,42,43,8,15,4,253,28,21,3,1,9,9,1,4,22,2,2,9,4,26,24,5,8,3,1,22,4,1,9,9,1,3,21,1,3,8,4,25,26,4,9,63,19,4,1,8,9,1,4,19,2,3,8,5,22,22,4,7,2,3,19,3,1,8,8,1,4,19,3,2,7,4,22, +22,5,8,3,1,249,39,43,38,254,180,40,1,41,38,251,40,43,38,112,23,4,1,9,9,1,3,21,2,2,8,3,26,25,4,8,3,1,21,2,1,8,9,1,3,22,1,3,8,6,24,25,5,9,2,252,242,37,5,1,13,14,1,5,37,4,4,13,7,43,41,8,12,4,4,36,4,1,14,13,1,4,36,4,2,14,8,42,43,8,15,2,3,132,5,42,69,5,7, +67,42,90,2,42,44,3,3,41,45,4,2,41,45,3,3,42,44,254,18,2,37,38,2,2,37,38,158,102,147,145,208,208,145,147,102,85,32,2,53,72,104,102,101,101,102,104,72,50,30,1,217,112,24,117,19,94,232,81,24,16,28,70,115,165,163,230,230,163,165,115,75,26,15,22,81,232,71, +254,129,31,52,13,13,52,31,3,16,9,3,20,19,3,9,14,2,30,50,15,15,50,30,2,14,8,4,19,20,4,8,16,1,48,31,52,14,14,52,31,3,16,7,3,21,19,4,9,14,2,30,50,14,14,50,30,2,14,9,4,19,21,4,6,16,1,57,17,29,10,10,29,17,3,10,4,2,13,10,2,14,1,17,30,7,7,30,17,1,7,7,2,10,13, +2,4,10,251,16,28,7,7,28,16,2,7,6,2,9,11,2,5,8,2,15,26,8,8,26,15,2,8,5,2,11,9,2,6,7,253,76,2,37,40,39,42,222,2,37,41,40,42,2,2,37,41,40,42,4,116,17,30,8,8,30,17,2,8,7,1,11,12,2,5,9,1,17,28,9,9,28,17,1,9,4,3,12,11,2,6,8,254,49,31,52,14,14,52,31,3,16,8, +3,20,19,4,9,14,3,29,50,14,14,50,29,3,14,9,4,19,20,4,7,16,0,0,0,0,15,0,29,0,48,4,180,5,114,0,19,0,33,0,50,0,67,0,84,0,101,0,118,0,135,0,152,0,169,0,186,0,203,0,220,0,237,0,254,0,0,1,22,7,6,15,1,6,43,1,38,39,38,53,52,63,2,54,23,22,7,6,23,22,31,1,22,63, +1,54,47,1,38,7,19,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,55,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,55,50,23,22,29,1,20,7,6,35,34,39,61,1,52,55,54,55,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,19,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54, +7,50,23,22,29,1,20,7,6,35,34,39,61,1,52,55,54,1,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,55,50,23,22,29,1,20,7,6,35,34,39,61,1,52,55,54,55,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,1,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,55,50,23,22,29,1,20, +7,6,35,34,47,1,53,52,55,54,55,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,55,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,1,108,61,46,15,37,16,71,92,17,38,29,35,45,31,9,76,106,46,196,78,26,4,10,11,48,100,38,75,17,24,52,105,185,21,11,6,20,8,10,27,9,1,19, +10,125,22,11,5,19,8,10,27,9,1,19,10,103,21,11,5,19,8,10,26,11,19,10,115,21,11,6,20,7,11,26,10,1,19,10,2,21,12,5,20,7,11,26,10,1,20,9,141,22,11,5,19,8,10,27,10,19,10,1,38,21,11,5,19,8,10,26,11,1,20,10,144,22,11,5,19,8,10,27,10,19,10,145,21,11,6,20,8,10, +27,9,1,19,10,254,2,22,11,6,20,8,10,27,9,1,19,10,204,21,12,5,20,7,11,26,10,1,20,9,217,21,11,6,20,8,10,26,10,1,19,10,193,21,12,5,20,7,11,26,10,1,20,9,1,198,72,131,53,45,19,86,5,34,42,60,67,90,43,10,93,2,9,95,95,102,17,12,13,56,65,37,92,109,36,61,70,1,14, +23,9,12,4,23,14,5,33,10,3,23,15,6,234,22,9,12,5,22,14,6,34,9,4,22,15,6,230,23,9,11,5,22,15,5,34,9,4,22,15,6,236,23,9,11,4,23,14,5,33,9,3,24,14,6,253,197,23,9,11,5,23,14,5,33,11,2,24,14,6,194,23,9,11,4,24,14,5,34,10,3,23,14,6,1,131,22,9,11,6,22,14,5,33, +9,4,22,16,5,187,23,9,11,5,23,14,5,34,9,3,23,15,6,194,24,9,11,4,23,14,6,34,10,3,23,14,7,252,77,22,9,11,5,23,14,6,34,9,4,23,14,6,158,22,9,11,5,22,15,6,35,9,3,23,15,5,172,23,9,10,5,24,13,5,33,10,2,24,14,6,151,23,9,11,4,24,13,6,34,10,2,24,14,6,0,0,1,0,58, +0,15,4,151,4,51,0,9,0,0,19,33,27,1,33,5,19,37,5,19,58,1,170,132,133,1,170,254,167,133,254,165,254,167,132,2,158,1,149,254,107,251,254,108,250,250,1,148,0,2,0,58,0,20,4,151,4,57,0,9,0,19,0,0,19,33,27,1,33,5,19,37,5,19,55,3,37,5,3,37,33,11,1,33,58,1,170, +132,133,1,170,254,167,133,254,165,254,167,132,48,100,1,9,1,18,109,1,28,254,167,104,100,254,165,2,164,1,148,254,108,251,254,108,250,250,1,148,15,254,203,191,201,1,64,199,1,56,254,200,0,0,1,0,200,0,5,4,9,5,214,0,17,0,0,1,22,23,20,7,9,1,55,19,37,55,1,38, +53,52,55,1,54,3,206,57,2,9,253,125,1,238,86,38,254,55,224,253,221,19,65,2,147,11,5,214,2,54,36,12,253,133,253,244,230,254,56,39,94,2,52,23,23,27,63,2,134,10,0,0,0,0,1,0,59,0,0,4,150,5,217,0,25,0,0,19,33,50,21,20,7,9,1,55,19,37,55,1,38,53,52,55,1,33,17, +20,35,34,53,17,52,122,3,214,60,26,253,229,1,201,83,35,254,78,216,254,16,14,49,1,199,253,12,68,67,5,217,83,34,27,253,197,254,27,213,254,61,34,108,2,22,15,46,27,51,1,223,250,252,69,68,5,91,58,0,0,0,0,3,0,43,0,7,4,166,4,129,0,13,0,25,0,38,0,0,1,20,0,35, +34,0,53,52,18,36,51,50,4,18,5,20,0,32,0,53,52,46,1,32,14,1,5,20,6,35,34,38,53,52,62,1,50,30,1,4,165,254,177,238,237,254,177,154,1,19,143,144,1,20,153,251,191,1,45,1,173,1,46,138,248,254,252,248,138,2,148,84,60,58,85,39,69,71,69,39,2,68,238,254,178,1, +78,238,149,1,20,148,148,254,237,150,214,254,211,1,45,214,136,246,133,133,246,136,60,83,83,60,38,69,36,36,69,0,0,3,0,15,0,5,4,194,5,29,0,10,0,22,0,67,0,0,0,34,6,21,20,22,51,50,54,53,52,37,34,6,21,20,22,51,50,54,53,52,38,37,22,23,22,21,20,6,35,34,38,53, +52,55,54,55,54,53,52,36,32,4,21,20,23,22,23,22,20,6,35,34,38,52,55,54,55,38,53,52,0,51,50,0,21,20,4,11,113,79,79,57,56,79,252,164,56,80,80,56,56,79,79,3,34,19,17,70,140,99,99,139,68,62,85,93,255,0,254,144,255,0,92,96,67,68,139,99,98,141,70,14,14,93,1, +87,246,248,1,87,1,177,90,65,64,90,90,64,65,90,90,65,64,91,91,64,65,90,75,15,20,80,114,113,160,160,113,114,80,71,8,101,134,157,222,222,157,134,100,3,77,80,228,160,160,228,80,15,13,125,159,217,1,50,254,206,217,155,0,0,0,3,0,18,255,254,4,191,5,107,0,10, +0,22,0,65,0,0,1,52,38,35,34,6,21,20,22,50,54,37,52,38,35,34,6,21,20,22,51,50,54,1,20,0,35,34,0,53,52,55,38,39,38,52,54,51,50,22,20,7,6,7,6,21,20,4,32,36,53,52,39,38,39,38,52,54,51,50,22,20,7,6,7,22,4,88,80,55,57,78,78,113,79,253,46,78,57,55,79,79,55, +57,78,3,39,254,171,247,245,254,171,93,14,14,69,139,97,99,139,68,67,95,92,0,255,1,110,0,255,92,85,62,68,139,98,99,138,69,17,19,88,4,70,68,98,98,68,69,97,97,69,69,97,97,69,68,97,97,254,43,232,254,185,1,71,232,169,132,14,17,85,242,171,171,242,85,83,3,106, +142,169,235,235,169,143,105,9,76,86,242,171,171,242,86,21,16,130,0,0,0,0,2,0,54,0,1,4,155,5,202,0,11,0,27,0,0,1,34,6,21,20,22,51,50,54,53,52,38,55,22,23,22,16,0,35,34,0,16,0,51,50,23,1,23,2,63,143,201,201,143,142,201,199,190,19,18,152,254,206,217,215, +254,206,1,47,218,96,84,1,14,154,3,99,200,144,142,201,201,142,144,200,59,16,19,153,254,80,254,207,1,49,1,176,1,50,29,1,211,89,0,0,3,0,46,0,3,4,163,5,203,0,8,0,17,0,49,0,0,1,34,6,20,22,50,54,52,38,0,34,6,20,22,51,50,54,52,1,22,21,20,2,35,34,2,53,52,18, +51,50,23,22,23,55,38,53,52,18,51,50,18,21,20,2,35,34,39,38,39,1,64,75,106,106,150,106,105,2,79,151,105,105,76,75,105,253,247,24,161,114,113,161,160,114,116,80,1,1,138,18,159,115,115,160,161,114,113,81,7,7,2,220,169,240,169,169,240,169,2,90,169,240,169, +169,240,253,228,84,100,181,254,255,1,1,181,183,1,1,128,3,2,137,73,85,183,1,1,254,255,183,181,254,255,129,11,12,0,0,14,0,20,255,255,4,189,4,200,0,23,0,41,0,53,0,65,0,77,0,89,0,100,0,112,0,123,0,134,0,145,0,157,0,169,0,181,0,0,1,51,4,23,22,21,6,47,1,38, +55,54,39,33,6,23,22,15,1,6,39,52,55,54,1,53,51,21,20,23,22,21,17,33,17,52,55,54,61,1,51,21,3,20,22,51,50,54,53,52,38,35,34,6,5,20,6,35,34,38,53,52,54,51,50,22,39,20,6,35,34,38,53,52,54,51,50,22,17,20,6,35,34,38,53,52,54,51,50,22,2,22,6,7,6,38,39,38,54, +55,54,19,22,6,7,6,38,39,38,54,55,54,22,1,30,1,14,1,39,46,1,55,62,1,4,30,1,7,14,1,39,46,1,55,54,36,54,22,23,22,6,7,6,38,39,38,37,54,22,23,22,6,7,6,38,39,38,54,1,62,1,23,30,1,7,14,1,39,46,1,19,62,1,23,30,1,7,14,1,39,46,1,2,102,5,1,60,135,142,20,59,214, +46,21,61,43,253,178,44,62,21,47,214,59,20,142,135,1,187,75,127,121,252,129,122,126,76,90,124,87,88,123,123,88,88,123,1,73,69,49,49,69,69,49,49,69,84,17,12,12,18,18,12,12,17,17,12,12,18,18,12,12,17,109,13,3,10,10,24,7,8,4,10,10,226,7,3,11,10,23,8,7,4, +10,10,24,254,249,13,10,7,22,12,11,12,4,4,22,1,59,23,11,4,4,22,11,12,11,4,4,254,201,23,22,4,3,10,12,12,22,4,4,1,82,11,22,4,4,11,12,11,23,3,4,11,254,255,7,24,10,10,4,8,6,25,10,10,4,202,8,23,10,11,3,7,7,24,10,10,4,4,200,14,127,135,139,133,8,115,22,64,100, +6,6,100,64,22,115,8,133,139,135,125,254,189,62,125,61,47,78,234,254,110,1,146,234,78,47,61,125,62,254,64,137,192,192,137,136,193,193,135,77,108,108,77,78,107,107,182,18,28,28,18,19,28,28,253,233,20,27,27,20,19,28,28,1,235,31,38,11,12,6,15,17,37,12,11, +254,73,16,37,13,10,5,17,15,37,12,10,5,1,34,7,33,36,18,5,6,35,18,18,18,160,12,34,18,18,17,6,6,33,19,18,5,12,17,18,19,34,7,4,17,18,18,200,6,18,18,18,33,7,6,18,18,18,33,254,214,15,5,10,12,38,14,17,5,10,13,37,1,177,16,6,11,12,37,17,15,6,12,11,38,0,0,0,16, +0,8,0,11,4,201,4,201,0,17,0,29,0,37,0,45,0,53,0,65,0,77,0,89,0,100,0,112,0,124,0,136,0,148,0,166,0,192,0,218,0,0,1,53,35,21,6,7,6,21,17,33,17,52,39,38,39,53,35,21,7,50,22,21,20,6,35,34,38,53,52,54,22,34,6,20,22,50,54,52,38,34,6,20,22,50,54,52,2,34,6, +20,22,50,54,52,3,14,1,23,30,1,55,62,1,39,46,1,19,14,1,23,30,1,55,62,1,39,46,1,37,6,22,23,22,54,55,54,38,39,38,6,5,6,22,23,22,62,1,38,39,38,6,5,30,1,55,62,1,39,46,1,7,14,1,37,30,1,55,62,1,39,46,1,7,14,1,3,22,54,55,54,38,39,38,6,7,6,22,19,22,54,55,54,38, +39,38,6,7,6,22,55,53,51,21,20,23,22,21,17,33,17,52,55,54,61,1,51,21,39,6,23,22,15,1,6,39,54,55,54,37,22,50,55,4,23,22,23,6,47,1,38,55,54,39,55,22,7,6,31,1,22,55,38,39,38,47,1,21,35,6,7,6,7,22,63,1,54,39,38,55,1,212,26,8,108,105,3,1,105,108,4,30,140,89, +122,123,88,87,124,123,137,98,69,69,98,69,100,25,17,17,25,17,17,25,17,17,25,17,145,10,4,7,8,24,10,10,3,7,7,24,185,10,4,7,7,25,10,10,4,8,7,24,254,236,4,12,11,12,22,4,3,10,13,11,22,1,56,4,11,11,12,22,7,11,11,12,22,254,193,4,22,12,12,10,3,4,22,12,11,12,1, +64,3,22,12,11,11,4,3,22,12,11,11,241,10,24,7,8,4,10,10,24,8,7,4,205,10,24,7,8,4,10,10,25,7,7,4,46,72,120,116,252,172,116,120,72,184,37,63,37,53,200,69,36,7,132,133,1,54,13,26,12,1,54,133,132,7,36,68,201,53,37,63,37,14,45,53,33,33,174,49,40,5,127,167, +255,26,29,255,167,126,6,40,49,175,32,32,53,44,3,26,52,116,52,40,52,196,254,178,1,78,196,52,40,52,116,52,59,188,132,133,187,187,133,132,188,141,104,150,104,104,150,224,26,37,26,26,37,254,35,26,37,26,26,37,1,216,11,36,16,14,7,11,12,37,15,14,6,254,95,12, +36,16,15,6,12,11,36,15,16,5,248,18,33,6,5,16,19,17,34,5,6,18,173,17,33,6,6,17,36,33,6,6,16,47,18,17,6,6,33,17,18,18,6,6,33,138,18,17,5,6,33,18,17,18,6,5,34,254,191,12,6,15,16,36,11,11,5,16,15,36,1,139,11,7,14,16,36,11,12,6,15,15,37,234,58,127,45,44,71, +217,254,140,1,116,217,71,44,45,127,58,186,13,88,76,15,134,8,172,162,82,113,14,1,1,14,113,82,162,172,8,134,15,76,88,13,23,33,91,36,31,110,30,147,128,91,105,20,1,1,20,105,91,128,147,30,110,31,36,91,33,0,0,0,2,0,111,0,4,4,98,4,8,0,7,0,11,0,0,19,33,23,17, +7,33,39,17,23,17,33,17,116,3,233,4,4,252,23,4,75,3,90,4,7,5,252,7,4,4,3,249,71,252,149,3,107,0,0,0,0,3,0,99,255,253,4,110,4,24,0,7,0,11,0,34,0,0,19,33,23,17,7,33,39,17,23,17,33,17,7,21,6,7,2,7,6,35,6,35,38,43,1,53,55,50,23,51,54,55,54,55,54,104,4,1,5, +5,251,255,5,78,3,110,95,53,29,230,44,4,11,83,9,71,144,16,114,106,51,5,35,45,69,109,68,4,24,4,251,239,5,5,4,17,74,252,130,3,126,111,4,46,40,254,201,227,42,33,182,4,52,92,116,82,126,131,85,0,0,0,0,3,0,133,0,5,4,76,3,218,0,7,0,11,0,26,0,0,19,33,23,17,7, +33,39,17,23,17,33,17,5,9,1,23,9,1,21,7,1,35,1,35,39,9,1,138,3,189,4,4,252,67,4,73,3,51,253,90,1,13,1,12,62,254,244,1,12,60,254,242,2,254,245,3,60,1,12,254,244,3,217,4,252,53,5,5,3,203,68,252,189,3,67,88,254,245,1,11,60,254,243,254,242,1,60,1,11,254,247, +59,1,14,1,13,0,0,0,1,0,201,0,89,4,8,5,68,0,20,0,0,1,51,1,54,1,50,55,51,23,9,1,21,7,1,35,1,35,39,1,0,53,1,38,5,1,60,12,1,43,4,7,4,90,254,192,1,64,92,254,193,2,254,191,3,92,1,68,254,188,5,67,253,236,9,1,251,16,90,253,228,253,232,3,89,2,23,253,235,92,2, +24,2,21,7,0,8,0,28,255,252,4,181,5,53,0,8,0,17,0,26,0,35,0,44,0,53,0,62,0,126,0,0,1,51,6,43,1,38,61,1,52,37,51,6,43,1,38,61,1,52,37,51,6,43,1,38,61,1,52,23,51,6,43,1,38,61,1,52,37,51,6,43,1,38,61,1,52,23,51,6,43,1,38,61,1,52,23,51,6,43,1,38,61,1,52,37, +51,23,21,51,32,19,22,29,1,35,38,39,38,43,1,34,7,21,20,7,39,38,35,17,20,15,1,34,47,1,53,55,51,23,21,22,59,1,50,63,1,17,34,7,6,35,39,53,55,35,38,39,35,34,15,1,35,53,54,55,54,51,53,1,31,2,21,64,4,41,1,163,1,20,65,4,40,1,123,2,21,64,5,40,173,2,21,64,4,41, +1,123,3,21,65,4,41,206,1,19,65,5,40,64,2,21,65,4,40,254,94,41,4,1,1,52,196,30,1,16,13,25,39,31,105,79,5,23,106,95,74,21,64,26,1,4,30,4,7,44,7,38,14,4,147,60,12,10,5,5,3,47,137,47,70,23,14,2,40,134,168,218,4,48,145,7,25,1,39,249,144,5,25,2,38,159,145, +6,25,2,38,130,144,5,25,2,39,220,144,5,25,2,39,74,144,4,26,2,38,164,145,6,25,1,40,108,4,78,254,210,53,9,5,9,29,15,62,33,9,1,41,38,254,86,63,15,1,60,17,16,4,4,7,63,36,25,1,165,38,36,4,8,32,39,17,38,11,1,90,135,139,78,0,9,0,78,0,6,4,131,5,130,0,9,0,15,0, +24,0,47,0,62,0,69,0,113,0,119,0,134,0,0,19,6,23,33,54,55,52,35,33,6,19,22,23,33,54,63,1,6,7,54,55,54,39,52,35,39,6,7,51,50,21,20,7,6,7,6,7,51,50,55,54,55,54,55,54,53,52,35,1,51,20,6,7,20,22,23,35,38,39,38,39,38,54,3,22,37,54,55,33,22,5,54,55,50,23,21, +20,15,1,23,20,7,33,38,61,1,55,53,36,47,1,53,54,51,22,23,38,17,52,51,33,22,21,51,50,21,20,7,6,7,6,43,1,39,1,22,23,33,54,55,3,6,7,6,7,35,62,1,53,52,38,53,51,30,1,176,1,12,3,42,8,2,21,252,236,19,44,4,11,2,199,10,6,51,6,41,61,34,22,2,23,40,1,1,38,41,48,31, +57,22,36,5,41,27,13,76,38,21,16,84,254,6,6,69,1,96,3,6,13,77,23,7,2,80,206,248,1,5,24,65,253,91,26,2,77,178,72,13,4,252,89,1,11,254,142,12,3,254,223,36,2,3,13,59,151,141,38,3,24,23,38,101,61,24,79,37,47,5,12,253,78,4,7,2,255,8,3,253,5,13,44,8,4,2,56, +40,4,7,46,2,143,55,76,49,82,21,4,254,224,24,17,21,20,187,102,126,1,72,56,83,16,81,27,30,44,122,72,37,1,57,68,54,13,29,41,106,71,80,64,2,246,52,128,82,106,100,166,137,95,42,75,102,115,251,68,22,20,15,142,73,82,23,9,9,10,15,57,33,10,14,7,6,15,6,2,2,79, +17,12,4,10,8,19,238,1,28,45,2,22,93,145,144,38,21,67,4,1,43,25,17,18,24,1,213,47,26,60,85,103,64,65,53,79,33,43,71,0,0,0,2,0,56,0,7,4,153,5,223,0,7,0,12,0,0,9,1,19,7,33,39,19,9,1,3,33,3,1,2,110,1,235,63,2,251,167,4,66,1,241,254,90,57,3,183,54,254,92, +5,223,254,119,251,180,3,6,4,76,1,134,254,53,252,95,3,161,1,75,0,0,0,0,1,0,47,0,2,4,162,5,210,0,9,0,0,9,1,19,23,7,33,39,19,0,55,2,108,1,241,66,2,2,251,149,4,68,1,230,16,5,210,254,119,251,191,3,3,6,4,68,1,128,6,0,1,0,38,0,7,4,171,4,196,0,66,0,0,1,39,38, +53,52,55,54,51,50,22,54,51,50,23,22,21,20,15,1,55,54,23,22,23,22,21,20,7,14,1,22,7,6,7,6,35,34,39,38,47,1,18,7,35,54,3,7,6,7,6,35,34,39,38,39,38,54,38,39,38,53,52,55,54,55,54,23,2,82,165,56,67,28,29,67,66,67,44,71,42,10,69,152,248,104,93,27,26,54,6,13, +101,59,22,8,25,44,48,25,27,81,58,157,31,110,72,136,30,157,59,80,27,25,48,43,26,9,21,59,101,13,6,54,26,27,92,105,2,126,250,84,90,87,52,18,88,88,92,34,31,103,94,225,82,41,32,10,22,53,54,17,17,46,39,95,69,30,22,33,10,27,83,226,254,190,241,241,1,66,226,83, +27,10,33,22,30,69,95,39,46,17,16,55,53,22,10,32,41,0,0,0,2,0,47,1,160,4,162,4,116,0,57,0,62,0,0,1,22,23,20,7,6,7,22,23,51,23,7,35,6,7,34,39,52,51,22,55,50,55,38,39,35,34,7,22,21,6,7,36,3,52,55,22,23,21,7,20,23,50,55,18,55,22,7,20,7,54,55,50,53,54,55, +54,38,3,6,23,53,38,3,251,85,15,56,134,15,195,41,21,15,36,2,13,116,74,19,15,12,46,59,9,199,5,3,100,51,102,7,255,254,44,34,51,39,6,10,86,68,10,40,227,153,4,32,71,76,47,55,59,59,44,103,11,185,24,4,116,4,94,70,21,29,36,22,221,60,10,142,7,76,68,38,1,63,62, +196,88,52,82,200,13,2,1,33,47,8,3,35,19,32,73,10,63,1,132,16,4,137,32,80,63,16,31,68,33,41,77,254,230,118,62,2,147,0,0,0,0,1,0,47,1,14,4,162,4,122,0,50,0,0,1,33,34,38,53,52,54,55,54,55,51,55,35,38,39,38,53,52,62,1,59,1,55,35,34,38,53,52,54,55,54,55,33, +55,33,34,38,53,52,62,1,51,33,54,55,54,51,33,50,22,21,4,104,253,244,33,46,21,19,14,14,41,3,103,36,19,24,22,39,19,137,1,196,51,48,23,19,15,17,1,1,2,253,185,33,47,22,38,20,2,106,6,13,23,33,1,29,32,47,1,14,58,40,26,47,12,9,3,11,2,24,29,41,25,47,26,10,57, +41,24,47,13,11,2,9,57,41,26,48,24,21,16,29,58,42,0,0,0,0,1,0,47,1,14,4,162,4,122,0,50,0,0,19,3,52,54,51,33,50,23,22,23,33,50,30,1,21,20,6,35,33,23,33,22,23,30,1,21,20,6,43,1,23,51,50,30,1,21,20,7,6,7,35,23,51,22,23,30,1,21,20,6,35,105,57,47,32,1,29,33, +23,13,6,2,106,20,38,22,47,33,253,185,2,1,1,17,15,19,23,48,51,196,1,137,19,39,22,24,19,36,103,3,41,14,14,19,21,46,33,1,14,3,8,42,58,29,16,21,24,48,26,41,57,9,2,11,13,47,24,41,57,10,26,47,25,41,29,24,2,11,3,9,12,47,26,40,58,0,0,0,0,2,0,14,1,26,4,195,4, +33,0,33,0,67,0,0,1,19,52,38,35,33,34,7,33,38,21,20,51,33,7,33,34,21,20,51,33,7,35,34,21,20,59,1,7,35,34,21,20,51,7,38,39,54,55,51,55,35,38,39,54,55,51,55,33,34,39,54,55,33,55,33,34,39,54,51,33,54,55,33,50,22,21,3,4,101,59,39,27,254,225,43,19,253,112, +67,67,2,111,10,254,224,67,67,0,255,7,180,67,67,142,16,50,67,67,23,75,1,1,75,60,4,139,76,1,1,76,185,2,255,0,75,1,1,75,1,37,3,253,147,74,1,1,74,2,148,26,54,1,48,34,50,61,1,50,2,129,30,41,46,2,61,60,61,61,60,64,61,58,62,61,59,24,1,84,84,1,11,1,85,83,1,15, +85,84,1,12,85,84,56,1,51,36,253,81,0,0,2,0,140,0,0,4,69,5,202,0,33,0,68,0,0,55,5,50,54,53,17,52,39,17,54,35,34,21,17,39,17,52,35,34,21,17,39,53,52,35,34,29,1,39,53,52,35,34,21,39,54,55,22,23,21,23,53,54,55,22,23,21,23,17,52,55,22,23,17,23,17,54,55,22, +21,17,22,23,17,20,6,35,37,19,170,3,21,36,52,58,2,74,73,76,76,72,79,75,72,76,75,73,29,1,104,103,1,14,1,104,103,1,18,105,103,1,15,1,104,103,68,2,62,45,252,178,1,115,74,49,32,1,98,54,22,3,39,83,83,253,2,13,1,99,82,82,254,196,9,223,83,83,174,18,63,83,83, +28,92,1,1,92,75,4,172,92,1,1,92,228,3,1,59,92,1,1,92,254,150,4,2,253,93,1,1,93,252,212,33,65,254,138,42,62,75,2,155,0,0,0,2,0,14,1,26,4,195,4,33,0,33,0,68,0,0,19,33,50,53,52,43,1,39,51,50,53,52,43,1,39,33,50,53,52,35,33,39,33,50,53,52,7,33,38,35,33,34, +6,21,1,48,33,3,52,54,51,33,22,23,33,50,23,6,35,33,23,33,22,23,6,35,33,23,51,22,23,6,7,35,23,51,22,23,6,108,2,31,67,67,50,16,142,67,67,180,7,0,255,67,67,254,224,10,2,111,67,67,253,112,19,43,254,225,27,39,2,113,253,170,61,50,34,1,48,54,26,2,148,74,1,1, +74,253,147,3,1,37,75,1,1,75,255,0,2,185,76,1,1,76,139,4,60,75,1,1,1,50,59,61,62,58,61,64,60,61,61,60,61,2,46,41,30,253,103,2,175,36,51,1,56,84,85,12,1,84,85,15,1,83,85,1,11,1,84,84,0,2,0,140,255,249,4,69,5,194,0,33,0,67,0,0,19,20,51,50,61,1,55,21,20, +51,50,61,1,55,17,20,51,50,53,17,55,17,20,51,50,39,17,54,53,17,52,38,35,5,39,37,50,22,21,17,6,7,17,20,7,38,39,17,7,17,6,7,38,53,17,7,21,6,7,38,39,53,7,21,6,7,38,39,170,73,75,76,72,75,79,72,76,76,73,74,2,58,52,36,252,235,30,3,78,45,62,2,68,103,104,1,15, +1,103,105,18,1,103,104,1,14,1,103,104,1,2,179,83,83,61,20,174,83,83,221,9,254,198,83,83,1,98,13,253,1,83,83,3,39,23,54,1,97,33,48,74,41,75,62,42,254,138,66,32,252,212,92,1,1,92,2,252,4,254,152,93,1,1,93,1,58,2,228,93,1,1,93,171,4,74,93,1,1,93,0,0,29, +0,12,255,254,4,197,4,191,0,79,0,128,0,136,0,144,0,159,0,174,0,181,0,188,0,205,0,211,0,218,0,222,0,226,0,230,0,234,0,238,0,242,0,246,0,250,0,254,1,2,1,17,1,29,1,33,1,37,1,41,1,45,1,49,1,53,0,0,1,50,23,22,29,1,20,7,23,21,20,7,51,54,53,54,59,1,50,21,22, +29,1,6,35,39,6,7,21,23,55,22,21,20,7,20,43,1,34,47,1,6,35,34,39,6,21,6,43,1,34,53,38,53,52,55,23,55,53,39,7,34,39,53,52,55,54,59,1,50,31,1,53,39,55,38,53,54,55,54,1,20,23,51,53,38,53,54,59,1,23,7,23,21,7,21,20,23,22,29,1,23,51,55,52,55,54,53,39,55,53, +39,55,22,29,1,7,23,54,61,1,52,39,38,43,1,32,7,6,5,22,7,6,39,34,39,52,33,22,23,6,35,34,39,38,19,51,54,51,23,54,53,38,53,38,35,6,7,6,21,37,6,35,6,21,23,55,22,23,53,52,39,38,53,38,5,23,21,7,38,53,52,55,22,21,20,7,39,53,3,22,51,54,55,38,55,6,7,6,43,1,38, +39,38,39,22,55,22,23,51,53,38,5,21,50,63,1,34,7,5,21,23,53,55,21,55,53,7,21,23,53,51,21,55,39,7,21,55,39,7,21,51,53,51,21,51,53,7,21,23,53,23,21,51,53,7,21,51,53,5,39,7,21,22,21,22,51,50,55,54,55,38,53,6,37,7,22,21,20,23,50,63,1,38,35,7,37,7,23,53,7, +21,23,53,39,21,23,53,23,21,55,53,55,21,55,53,55,21,55,53,2,117,233,111,44,77,5,19,4,122,34,27,6,48,54,20,48,68,189,47,178,53,73,58,50,4,39,53,144,58,131,134,54,160,38,34,11,42,58,68,58,173,231,83,52,6,54,3,30,25,36,46,101,19,9,81,26,201,78,254,240,53, +5,23,8,10,10,14,10,25,15,117,52,77,68,97,149,25,20,26,10,23,19,23,4,54,170,98,85,29,254,254,80,15,1,25,43,10,44,72,59,27,1,96,155,4,28,73,50,51,2,181,4,214,18,78,24,53,6,15,21,40,189,253,13,13,10,40,35,73,48,183,77,154,19,1,211,10,39,29,94,53,31,37,204, +35,163,165,33,5,25,27,21,58,88,43,145,9,6,34,22,7,15,19,5,7,1,42,11,3,19,10,18,254,236,14,222,20,227,19,155,21,2,54,18,3,87,24,15,19,125,19,87,19,58,24,254,117,87,5,52,5,10,15,53,118,26,14,142,2,84,13,173,38,16,9,47,4,24,72,254,51,3,23,19,19,86,19,156, +20,12,19,15,20,4,190,156,88,68,57,92,83,76,5,43,38,51,49,46,100,43,28,19,37,6,88,33,15,81,10,14,36,31,50,96,96,75,80,80,80,20,71,91,54,37,35,10,10,81,15,121,6,45,11,22,54,91,91,51,5,71,75,91,175,187,79,23,254,194,96,95,65,91,45,41,15,36,116,55,136,10, +76,25,45,36,20,10,21,76,54,29,61,152,127,15,34,17,9,28,40,141,20,67,74,35,171,82,34,196,48,169,13,58,130,4,126,71,8,66,123,126,69,254,111,106,4,6,8,60,30,52,8,83,91,16,191,90,30,21,8,4,15,97,11,76,21,67,53,29,11,5,129,41,10,46,85,37,43,90,38,7,41,131, +254,205,162,12,155,55,101,31,141,60,18,73,76,65,97,77,30,111,75,51,51,75,64,71,54,11,36,4,36,4,40,8,38,12,40,4,39,39,6,38,5,49,2,47,4,45,45,45,45,50,41,4,40,11,40,45,5,40,40,100,4,4,16,46,39,45,84,63,24,30,24,79,75,56,84,36,12,33,84,51,15,4,166,40,5, +45,60,40,5,40,26,39,6,41,20,41,5,41,3,40,4,41,8,41,6,40,0,0,1,0,9,255,251,4,200,5,211,0,38,0,0,1,50,23,22,21,20,7,1,7,20,23,37,50,23,21,20,35,5,34,39,38,61,1,52,55,0,55,54,53,52,39,35,5,34,39,53,52,55,51,2,244,116,92,42,101,253,232,9,79,2,201,64,7,85, +253,67,131,88,22,113,1,249,16,9,80,9,253,83,46,9,80,11,5,211,141,77,79,138,98,253,160,62,89,26,209,97,3,89,198,174,53,56,24,138,108,2,55,27,27,22,80,32,204,80,30,64,12,0,0,0,0,6,0,8,0,2,4,201,4,195,0,17,0,36,0,48,0,60,0,70,0,88,0,0,1,32,19,22,21,16,5, +6,43,1,32,3,38,61,1,16,37,54,5,38,35,34,7,6,21,16,23,22,51,32,19,54,61,1,16,37,38,3,35,34,39,19,22,59,1,50,55,19,6,3,6,29,1,33,53,52,55,54,55,19,6,37,22,23,33,38,39,38,39,19,22,5,50,23,22,21,20,7,6,43,1,34,39,38,61,1,52,55,54,2,94,1,55,215,92,254,255, +158,172,26,254,203,213,80,1,18,151,1,184,135,135,244,191,103,227,145,181,1,21,190,72,254,236,4,244,22,137,114,169,39,46,6,41,37,173,115,234,77,254,167,233,14,16,170,5,2,13,77,2,254,166,1,25,27,35,170,102,254,155,67,45,20,55,33,37,6,65,46,17,59,32,4,194, +254,211,142,174,254,239,206,119,1,58,142,144,23,1,19,210,107,139,75,240,143,158,254,255,183,113,1,26,122,134,13,1,24,182,3,252,43,72,1,42,25,24,254,214,71,2,144,59,77,4,13,234,178,10,10,254,214,3,116,117,143,47,38,40,21,1,40,65,247,65,30,38,58,43,26, +67,30,31,4,59,46,23,0,0,6,0,34,0,7,4,175,4,47,0,9,0,19,0,29,0,56,0,80,0,105,0,0,1,62,1,39,54,55,22,6,7,38,3,38,6,7,38,39,54,22,23,6,5,20,22,23,6,7,46,1,55,22,1,6,35,34,39,38,39,7,6,7,6,35,34,39,22,54,55,54,39,55,22,55,23,6,23,30,1,3,22,23,22,7,51,22, +23,22,29,1,46,1,35,6,7,39,54,39,53,54,55,54,38,1,38,53,52,55,54,23,39,38,39,54,55,14,1,23,22,31,1,6,23,7,38,7,38,6,2,220,48,55,5,26,26,9,94,60,12,5,49,120,44,23,15,66,177,53,18,254,177,64,50,2,11,74,86,8,30,2,171,77,118,33,35,117,65,1,43,85,66,68,88, +91,102,185,42,59,45,49,48,41,46,46,67,44,157,183,115,66,35,72,2,75,85,139,9,149,80,130,93,49,5,50,129,60,48,27,252,209,3,86,81,137,1,31,2,12,196,125,37,39,72,136,1,54,8,45,84,125,94,128,1,36,29,107,55,10,4,82,151,26,27,1,135,27,5,31,16,20,50,7,39,23, +198,55,102,23,27,24,33,157,65,4,254,92,59,5,25,121,1,63,49,33,53,48,66,69,116,132,30,34,33,28,122,107,81,59,4,15,48,154,113,117,7,48,92,183,7,111,130,7,105,29,58,19,53,22,111,80,165,253,90,17,17,106,115,88,4,1,70,97,192,80,74,194,71,108,27,59,24,52,26, +101,4,1,106,0,0,23,0,78,255,255,4,131,5,94,0,3,0,19,0,25,0,29,0,49,0,70,0,91,0,113,0,139,0,149,0,154,0,159,0,164,0,169,0,174,0,179,0,184,0,189,0,194,0,199,0,204,0,209,0,252,0,0,1,6,55,38,23,38,7,6,39,55,39,54,23,22,23,6,7,38,39,36,1,6,7,35,38,55,3,22, +39,38,19,21,6,35,34,39,53,38,55,54,55,22,23,6,7,6,4,7,35,38,39,21,39,53,36,39,54,55,22,23,6,7,6,4,23,22,7,39,54,39,54,3,21,39,53,36,39,54,55,22,23,6,23,6,4,23,6,7,39,54,53,54,7,38,39,54,55,22,23,6,21,20,4,23,6,7,38,39,54,39,38,39,21,39,19,21,39,53,36, +55,54,55,54,23,7,23,6,39,38,7,6,4,23,6,7,38,39,54,39,54,1,20,30,1,51,38,55,34,14,1,5,22,23,55,38,39,22,23,55,38,39,22,23,55,38,39,22,7,55,38,39,22,7,23,54,39,6,7,23,54,37,23,54,55,6,7,23,54,55,6,7,23,54,55,6,31,1,38,55,6,23,55,38,55,6,23,55,38,39,6,23, +21,39,53,38,7,34,39,54,37,22,23,22,51,53,38,39,46,1,53,52,62,1,50,30,1,21,20,6,7,6,7,51,20,35,21,54,55,4,23,6,35,38,3,5,16,56,9,112,10,43,87,68,84,99,39,72,188,12,2,130,64,145,1,1,254,162,88,28,14,1,79,96,61,19,32,220,10,24,31,3,161,1,4,59,42,41,56,1, +2,1,32,2,14,24,107,68,254,255,4,2,118,47,80,157,3,5,1,146,5,4,107,45,74,12,1,75,68,254,176,2,4,104,71,97,202,13,9,2,68,1,4,138,96,150,2,235,247,5,1,103,66,68,150,1,234,3,4,160,30,54,166,5,2,172,68,68,68,254,159,1,12,188,61,51,100,84,68,87,44,9,3,2,155, +6,6,160,58,103,242,1,11,254,149,17,30,17,28,28,16,31,17,1,151,106,41,25,89,138,105,35,39,87,116,73,16,45,57,119,49,1,56,36,94,2,23,56,2,59,46,47,55,45,253,73,25,41,106,83,41,39,35,105,92,18,45,16,73,77,15,57,2,49,68,59,56,23,2,37,97,55,47,46,7,216,68, +61,117,246,82,78,1,66,22,82,1,1,2,2,19,21,21,38,39,37,22,21,18,3,3,1,1,81,22,1,66,78,82,246,113,3,207,32,22,18,100,50,10,31,14,21,23,68,13,3,115,57,30,16,8,18,253,16,31,56,67,32,3,91,24,34,8,252,124,52,24,52,38,27,51,44,22,12,5,20,17,39,50,94,51,159, +82,12,84,40,66,63,29,18,8,23,35,39,57,67,45,13,11,18,33,21,1,121,129,12,126,35,90,49,20,19,6,15,29,48,62,78,63,30,25,36,23,37,151,30,89,52,28,11,7,30,41,37,70,78,63,19,13,10,29,40,28,27,123,11,1,219,117,8,115,19,105,115,4,3,60,22,21,14,32,10,51,40,38, +94,84,18,15,14,25,48,29,2,53,17,29,16,60,62,15,30,55,59,44,35,52,20,91,58,31,79,40,118,65,17,102,71,135,69,7,116,89,143,66,10,122,94,126,52,23,106,10,35,44,59,16,98,31,58,91,39,126,17,65,118,64,126,7,69,135,81,130,10,66,143,97,107,23,52,126,95,170,190, +6,178,72,35,152,84,6,50,27,1,22,1,1,10,36,20,19,36,20,20,36,19,20,36,10,1,1,1,20,27,50,6,84,152,34,0,0,0,2,0,96,255,255,4,113,5,216,0,7,0,36,0,0,1,38,39,6,7,22,23,54,7,38,39,54,55,22,23,22,7,51,50,55,17,38,7,35,17,20,23,33,54,53,17,35,38,7,17,22,51,2, +214,2,106,106,1,7,100,110,175,104,10,2,177,177,3,4,119,143,158,152,150,160,143,87,254,209,86,147,159,150,152,158,4,221,177,2,2,177,142,113,90,114,101,184,243,2,2,243,194,91,99,254,247,55,1,254,12,181,174,174,181,1,244,1,55,1,9,99,0,0,0,3,0,121,255,254, +4,88,5,218,0,3,0,32,0,44,0,0,1,21,51,53,39,53,51,21,51,21,35,21,51,5,21,33,17,23,21,39,3,35,3,39,53,23,17,33,53,33,53,35,53,19,51,17,33,53,33,53,35,21,33,21,33,1,252,202,182,170,126,126,10,1,148,254,98,144,136,2,176,2,134,134,254,108,1,150,118,164,70, +1,12,254,244,70,254,244,1,12,5,65,60,60,51,102,102,162,88,1,175,253,232,139,156,133,254,238,1,188,134,155,130,1,113,176,88,162,252,207,1,187,71,99,99,71,0,0,0,2,0,97,0,7,4,112,6,2,0,7,0,32,0,0,1,17,51,50,54,52,38,35,1,17,33,50,22,21,20,6,43,1,21,55,51, +9,1,35,39,21,35,53,7,35,9,1,51,2,109,171,96,104,104,96,254,206,1,50,169,174,174,169,171,179,180,254,177,1,96,179,196,136,209,179,1,104,254,182,181,5,124,254,59,118,217,118,252,188,3,202,183,177,178,182,252,194,254,147,254,125,214,214,228,228,1,138,1, +102,0,0,0,1,0,204,255,251,4,5,5,205,0,31,0,0,1,51,23,21,51,23,21,7,35,21,33,23,21,7,33,17,7,35,39,17,33,39,53,55,33,53,35,39,53,55,51,53,2,12,182,6,175,6,6,175,1,54,7,7,254,202,6,182,6,254,204,6,6,1,52,174,5,5,174,5,205,5,154,6,148,6,112,6,152,5,252, +134,5,5,3,122,5,152,6,112,6,148,6,154,0,0,0,1,0,55,0,1,4,154,4,100,0,43,0,0,1,33,23,21,7,35,17,33,53,55,51,23,17,7,35,39,53,33,17,51,23,21,7,33,39,53,55,51,17,33,21,7,35,39,17,55,51,23,21,33,17,35,39,53,1,196,1,73,4,4,120,1,172,5,79,5,5,79,5,254,84,120, +4,4,254,183,4,4,128,254,83,5,86,4,4,86,5,1,173,128,4,4,100,5,89,4,254,92,121,5,5,254,183,5,5,118,254,86,4,80,4,4,80,4,1,170,118,5,5,1,73,5,5,121,1,164,4,89,0,2,0,30,0,3,4,179,5,39,0,27,0,44,0,0,1,51,50,23,35,39,32,3,6,21,16,5,22,51,55,21,6,7,6,43,1,32, +3,38,53,16,37,54,1,51,50,23,51,21,7,22,21,39,7,35,53,55,39,53,51,2,109,16,175,166,4,189,254,240,165,74,1,14,108,123,203,126,109,64,43,22,254,221,188,104,1,52,136,1,250,2,5,49,165,133,52,140,134,2,52,136,168,5,39,129,48,254,239,138,163,254,190,188,62, +44,5,95,22,10,1,23,169,205,1,118,210,78,254,107,177,3,110,165,15,109,109,3,177,110,3,0,0,0,0,4,0,8,0,0,4,201,4,193,0,22,0,79,0,98,0,115,0,0,1,22,51,50,55,22,51,50,55,53,51,23,21,20,15,1,34,39,6,35,34,39,52,23,51,22,23,50,21,3,51,54,17,52,39,53,22,29, +1,20,7,6,7,21,22,59,1,21,6,43,1,34,7,39,35,34,39,53,51,50,55,53,39,38,39,38,53,52,63,1,21,6,21,16,23,53,3,53,55,50,39,21,6,7,6,21,20,23,21,35,38,39,38,53,52,55,54,51,52,37,22,23,22,29,1,20,7,6,7,52,55,54,61,1,16,39,1,220,22,52,38,26,31,35,54,17,4,2,56, +25,36,28,27,36,66,13,144,2,41,27,7,8,1,238,90,181,182,62,38,65,134,21,95,59,105,17,56,56,117,45,111,49,98,70,71,102,29,81,162,27,95,239,15,3,28,208,77,53,109,119,2,128,76,31,218,98,29,2,4,107,106,143,135,73,25,44,75,242,4,192,61,39,39,56,5,32,4,48,22, +3,35,35,82,27,109,52,9,4,252,218,185,1,43,158,168,2,175,225,29,220,180,53,18,4,33,4,27,80,80,23,4,34,3,52,92,61,143,144,209,187,25,4,156,184,254,232,199,2,2,142,18,138,34,5,56,81,165,195,189,174,1,60,189,87,84,218,166,57,3,2,25,91,148,176,38,172,148, +66,5,6,67,142,155,2,1,40,198,0,0,0,0,3,0,103,255,249,4,106,5,91,0,84,0,95,0,103,0,0,1,50,23,15,1,22,23,22,21,20,7,21,35,21,50,55,54,53,52,39,55,51,22,21,16,3,38,35,34,21,20,23,22,7,6,35,6,39,38,39,21,6,23,20,35,34,53,54,61,1,6,21,6,39,34,39,52,54,39, +52,35,34,7,2,17,52,55,51,23,6,21,20,23,22,23,53,35,53,38,53,52,55,47,1,54,3,20,23,51,54,53,52,39,6,7,6,37,6,21,20,23,54,53,52,2,105,61,75,17,14,117,47,51,188,110,111,131,124,115,20,4,215,137,110,73,51,110,30,2,12,39,59,6,54,87,4,78,96,102,73,141,7,58, +37,13,141,3,43,75,107,141,209,5,19,115,197,58,111,109,188,219,22,15,80,189,124,4,64,26,82,47,37,1,83,32,60,133,5,91,69,14,114,42,74,75,78,183,90,69,110,118,145,182,162,105,17,152,237,254,247,254,226,160,41,26,135,37,42,54,8,38,219,45,138,67,108,54,55, +106,71,135,86,176,34,2,54,59,155,30,37,159,1,10,1,50,214,153,17,112,160,231,150,43,16,110,69,85,187,175,95,114,17,66,254,40,134,69,97,128,76,116,23,68,58,149,106,91,126,94,57,154,140,0,0,0,1,0,15,0,5,4,194,5,34,0,50,0,0,1,50,23,22,21,20,7,23,7,35,39, +6,35,34,39,21,3,35,38,39,54,1,54,51,22,51,50,55,39,7,35,38,39,55,22,21,7,22,23,53,54,61,1,52,39,38,43,1,34,7,54,2,171,190,169,120,100,156,113,2,149,133,175,137,115,209,2,165,3,21,1,22,19,6,91,127,154,121,174,87,5,151,7,188,227,101,185,23,54,202,111,96, +29,79,97,137,5,33,165,136,188,176,121,129,115,149,96,77,3,254,107,123,6,22,1,101,26,75,91,174,101,102,10,226,12,5,139,153,12,1,79,109,31,222,89,60,48,125,0,5,0,27,0,5,4,182,4,160,0,11,0,18,0,22,0,26,0,33,0,0,19,52,0,51,50,0,21,20,0,35,34,0,55,20,23,1, +3,6,0,19,22,23,27,1,54,55,9,1,54,53,52,0,39,17,27,1,89,244,245,1,89,254,167,245,244,254,167,120,95,1,80,2,154,254,237,136,139,151,2,75,161,134,254,217,1,92,89,254,236,166,2,81,245,1,90,254,166,245,244,254,169,1,87,244,180,95,1,139,1,98,3,254,237,253, +241,140,4,1,229,254,25,6,129,1,89,254,228,88,193,196,1,19,3,254,161,0,0,0,0,4,0,14,0,5,4,195,4,186,0,18,0,30,0,40,0,52,0,0,1,21,30,1,51,50,54,53,52,0,35,34,0,7,62,1,51,50,22,5,20,6,35,34,38,53,52,54,51,50,22,5,52,38,34,6,21,20,22,50,54,37,20,0,35,34, +0,53,52,0,51,50,0,2,105,8,158,116,118,161,254,179,228,234,254,199,16,19,143,120,115,159,1,113,49,31,34,48,48,34,32,48,253,205,47,66,47,47,66,47,3,35,254,160,250,250,254,159,1,97,250,250,1,96,2,105,21,114,155,166,124,224,1,72,254,199,250,138,144,155,127, +33,47,47,33,34,48,48,34,34,48,48,34,33,47,48,32,250,254,161,1,95,250,250,1,98,254,158,0,10,0,27,0,168,4,182,5,35,0,14,0,62,0,68,0,74,0,80,0,86,0,92,0,98,0,104,0,110,0,0,1,20,23,22,50,55,54,53,52,39,38,35,34,7,6,5,38,55,51,54,55,39,54,55,23,54,55,53,54, +23,21,22,23,55,22,23,7,22,23,51,22,7,35,6,7,23,6,7,39,6,7,21,6,39,53,38,39,7,38,39,55,38,39,37,54,55,39,6,7,5,22,23,55,38,39,1,54,55,39,6,7,37,22,23,55,38,39,1,38,39,7,22,23,37,6,7,23,54,55,5,6,7,23,54,55,37,38,39,7,22,23,1,234,38,36,104,37,36,37,37, +51,52,36,38,254,49,43,43,88,21,83,65,11,78,64,96,152,61,61,142,107,62,80,13,67,82,22,88,43,43,88,15,89,67,13,80,62,107,142,61,61,141,108,63,76,13,63,81,21,1,139,26,28,9,111,76,1,43,32,23,143,78,110,254,249,7,17,159,59,18,2,80,19,5,214,15,63,253,252,16, +8,212,17,59,2,28,6,18,160,64,13,254,203,26,29,10,110,77,254,211,22,31,143,78,110,2,228,51,37,37,37,37,51,52,37,38,38,37,115,61,61,143,96,63,74,12,62,80,23,87,44,44,87,17,87,63,11,75,63,95,144,61,61,137,102,63,72,8,63,80,23,87,44,44,87,18,85,63,8,72,63, +94,145,234,15,8,210,17,60,133,8,15,155,61,16,254,161,29,21,133,75,101,43,24,26,8,99,76,254,171,24,32,13,109,67,190,29,27,134,80,96,107,14,8,213,24,60,129,7,15,151,60,24,0,0,0,0,5,0,33,0,164,4,176,5,52,0,15,0,30,0,40,0,48,0,56,0,0,19,52,55,54,51,50,23, +22,21,20,7,6,35,34,39,38,55,20,23,22,51,50,55,54,53,52,0,35,34,7,6,1,38,7,35,18,37,4,19,35,38,55,38,39,54,55,22,23,6,5,38,39,54,55,22,23,6,33,171,171,241,243,171,170,170,171,243,241,171,171,118,137,136,192,193,137,137,254,238,193,192,136,137,1,211,164, +61,54,15,1,12,1,4,15,53,78,39,86,3,4,91,83,4,4,254,46,85,4,5,91,82,5,5,2,234,243,171,172,172,171,243,241,171,170,170,171,241,191,137,138,138,137,191,195,1,16,136,136,254,222,10,204,1,16,14,18,254,245,202,175,4,88,91,5,7,86,91,4,4,88,91,5,7,86,91,0,0, +5,0,33,0,164,4,176,5,52,0,15,0,30,0,40,0,48,0,56,0,0,19,52,55,54,51,50,23,22,21,20,7,6,35,34,39,38,55,20,23,22,51,50,55,54,53,52,0,35,34,7,6,1,22,55,51,2,5,36,3,51,22,1,38,39,54,55,22,23,6,5,38,39,54,55,22,23,6,33,171,171,241,243,171,170,170,171,243, +241,171,171,118,137,136,192,193,137,137,254,238,193,192,136,137,1,209,166,61,54,15,254,243,254,253,15,51,81,1,78,86,3,4,91,83,4,4,254,46,85,4,5,91,82,5,5,2,234,243,171,172,172,171,243,241,171,170,170,171,241,191,137,138,138,137,191,195,1,16,136,136,254, +119,9,204,254,240,14,19,1,10,202,1,39,4,88,91,5,7,86,91,4,4,88,91,5,7,86,91,0,0,0,0,4,0,33,0,164,4,176,5,52,0,15,0,25,0,33,0,41,0,0,19,52,55,54,51,50,23,22,21,20,7,6,35,34,39,38,37,35,18,5,36,19,39,6,39,6,1,38,39,6,7,22,23,54,37,38,39,6,7,22,23,54,33, +171,171,241,243,171,170,170,171,243,241,171,171,1,52,62,18,1,59,1,68,18,64,75,199,178,2,6,6,99,110,6,5,103,107,254,63,5,100,110,5,4,104,107,2,234,243,171,172,172,171,243,241,171,170,170,171,237,254,189,22,17,1,73,2,248,11,10,1,214,107,8,6,112,105,7,7, +110,105,8,6,112,105,7,7,0,0,10,0,33,0,164,4,176,5,52,0,7,0,12,0,19,0,34,0,42,0,50,0,58,0,65,0,73,0,88,0,0,1,51,23,17,7,35,39,17,5,23,21,7,39,37,23,7,35,38,39,53,5,50,31,1,20,7,6,35,34,39,38,53,52,55,54,5,33,23,21,7,33,39,53,37,33,23,21,7,33,39,53,7,51, +22,23,21,7,39,53,37,51,23,21,7,39,53,37,51,23,17,7,35,39,17,3,6,21,20,23,22,51,50,55,54,53,39,38,35,34,2,77,61,5,5,61,4,1,188,44,194,47,253,165,197,48,3,156,35,1,182,168,72,10,153,56,38,141,79,29,148,54,253,227,1,9,5,5,254,247,4,3,124,1,14,5,5,254,242, +5,55,2,105,89,48,194,254,54,2,46,193,47,1,164,61,5,5,61,4,29,101,19,54,97,25,38,105,7,49,114,31,5,52,5,254,238,5,5,1,18,122,48,2,199,49,185,198,50,156,43,3,142,176,75,147,78,19,131,50,72,140,81,21,214,5,62,5,5,62,5,5,62,5,5,62,219,102,94,2,50,198,3,34, +47,3,198,49,3,93,5,254,238,5,5,1,18,1,211,56,96,49,34,89,13,52,102,50,121,0,0,2,0,156,0,5,4,53,5,198,0,23,0,43,0,0,1,32,1,22,21,16,5,6,43,1,34,39,53,36,55,54,17,16,37,38,39,53,52,55,23,21,4,17,16,5,7,21,51,50,55,54,55,54,61,1,16,1,38,35,1,59,1,133,1, +12,104,254,122,176,173,48,47,79,1,16,123,153,254,183,134,91,146,40,1,194,254,180,42,6,84,156,229,81,28,254,171,161,155,5,197,254,141,170,195,254,126,253,96,14,6,78,174,199,1,8,1,138,220,79,16,3,10,14,61,3,194,254,28,254,116,228,24,4,82,150,240,91,92, +9,1,56,1,1,100,0,0,0,0,2,0,149,0,7,4,60,5,223,0,23,0,43,0,0,37,32,1,38,53,16,1,54,59,1,50,23,21,4,7,6,17,16,5,22,23,21,20,7,39,53,36,17,16,37,55,53,35,34,7,6,7,6,29,1,16,1,22,51,3,154,254,118,254,238,104,1,140,178,178,48,46,80,254,236,126,154,1,78,136, +94,150,40,254,56,1,80,44,6,86,160,232,82,28,1,90,164,158,7,1,121,173,198,1,136,1,1,99,15,7,79,177,203,254,245,254,112,225,79,16,4,10,14,62,3,197,1,237,1,145,232,24,3,83,150,245,92,94,9,254,194,254,252,102,0,0,0,0,2,0,189,255,96,4,20,5,171,0,49,0,66,0, +0,1,22,23,22,21,20,7,6,7,21,55,21,7,23,35,53,35,53,51,39,38,39,38,53,52,55,54,55,38,39,38,61,1,51,21,20,23,22,23,51,54,55,54,61,1,51,21,20,7,6,7,35,6,7,6,21,20,23,22,51,50,55,54,53,52,39,38,3,79,38,34,125,124,102,135,204,208,1,122,191,191,2,139,103,125, +125,34,38,38,34,125,134,85,81,110,36,109,81,85,134,125,34,250,36,110,81,85,86,86,123,120,86,86,85,81,4,60,25,34,123,179,177,117,94,14,197,2,94,1,191,192,92,197,13,95,117,177,179,123,34,25,23,35,124,177,8,10,122,85,79,6,6,79,85,122,10,8,177,124,35,89, +6,79,84,123,122,81,80,80,81,122,123,84,79,0,0,0,2,0,145,255,155,4,64,5,62,0,14,0,41,0,0,1,52,39,38,35,34,7,6,21,20,22,51,50,55,54,5,38,53,52,55,54,51,50,23,22,21,20,7,6,7,21,55,21,7,23,35,39,35,53,51,39,38,3,173,96,95,132,135,95,95,190,135,132,95,96, +253,111,139,138,138,197,194,138,138,137,113,147,223,228,2,135,2,209,209,1,153,3,107,135,93,94,94,93,135,134,178,89,89,193,129,195,197,136,137,137,136,197,195,129,104,15,217,1,103,2,209,211,102,217,14,0,0,0,2,0,145,255,155,4,64,5,62,0,12,0,39,0,0,1,34, +7,6,16,22,51,50,55,54,16,39,38,39,55,35,53,51,55,51,7,23,21,39,21,22,23,22,21,20,7,6,35,34,39,38,53,52,55,54,2,106,135,95,95,190,135,132,95,96,96,95,200,1,209,209,2,135,2,228,223,147,113,137,138,138,194,197,138,138,139,113,2,165,89,88,254,242,186,93, +93,1,14,88,89,134,218,102,211,210,1,104,2,218,15,104,129,195,196,136,137,137,136,196,195,129,106,0,0,2,0,21,0,154,4,188,5,48,0,13,0,39,0,0,1,38,39,38,7,6,20,23,22,51,22,55,54,38,19,6,43,1,34,39,38,53,39,52,55,54,23,22,23,1,37,55,33,17,7,17,1,22,23,22, +2,162,90,123,122,91,90,90,91,126,127,92,89,8,16,131,182,1,185,130,129,2,131,130,178,178,87,1,26,254,222,109,1,130,112,254,231,78,7,6,3,35,90,4,4,88,91,254,91,89,1,90,91,246,254,80,128,128,129,183,3,182,131,129,7,6,81,1,16,2,109,254,128,112,1,35,254,239, +84,178,177,0,0,0,0,1,0,71,0,42,4,138,5,174,0,31,0,0,1,53,50,55,54,52,39,38,35,34,7,6,29,1,35,52,54,51,50,23,22,21,20,7,51,17,51,17,35,17,33,53,1,232,115,80,81,80,80,116,114,81,80,142,244,173,177,121,122,103,214,143,143,252,76,2,31,1,81,81,228,81,80,80, +81,114,2,174,246,123,123,174,159,116,3,143,250,124,1,103,142,0,0,1,0,174,0,42,4,35,5,174,0,34,0,0,1,35,53,51,53,51,21,51,21,35,17,54,51,50,23,22,21,20,6,29,1,35,52,55,54,53,52,38,35,34,7,6,21,17,35,1,18,100,100,143,168,168,105,144,167,113,113,132,143, +67,66,146,105,103,73,73,143,4,117,143,170,170,143,254,147,103,122,121,177,85,216,114,2,125,112,112,68,116,160,80,81,115,254,95,0,0,0,2,0,67,0,133,4,142,5,83,0,13,0,55,0,0,1,34,7,6,21,20,22,50,55,54,53,52,39,38,55,22,23,22,21,20,7,6,35,34,38,53,52,55, +54,55,17,35,17,35,53,51,17,35,53,51,17,51,17,51,17,51,17,51,21,35,17,51,21,35,17,35,2,104,46,32,32,64,92,32,33,32,32,16,50,40,62,62,63,90,87,126,62,39,51,237,251,127,127,251,237,124,237,250,125,125,250,237,1,203,33,32,45,47,64,32,32,47,45,32,33,94,15, +39,63,88,89,63,63,126,89,88,63,40,14,1,70,254,152,125,2,82,125,254,152,1,104,254,152,1,104,125,253,174,125,1,104,0,0,0,0,1,0,76,0,133,4,133,5,83,0,60,0,0,1,21,35,53,35,53,51,53,38,39,38,39,53,7,39,55,51,23,21,39,21,51,21,35,22,23,22,23,17,7,39,55,51, +23,21,39,17,54,55,54,61,1,51,53,7,39,55,51,23,21,39,21,49,21,20,7,6,7,21,51,21,2,167,124,144,144,135,101,123,1,118,1,119,125,119,119,2,2,1,85,65,84,119,1,120,124,120,120,83,64,87,1,119,1,120,125,118,118,124,100,136,144,1,31,154,154,124,114,18,101,123, +177,69,117,115,126,126,115,117,69,2,124,86,65,16,2,75,116,114,127,127,114,116,253,182,16,64,88,123,1,73,117,115,126,126,115,117,73,4,173,123,100,19,114,124,0,0,0,0,2,0,215,0,42,3,250,5,174,0,18,0,29,0,0,19,33,32,23,22,21,20,7,6,35,33,17,33,23,21,7,33, +39,17,23,17,33,50,55,54,55,52,39,38,35,223,1,129,1,29,95,30,237,56,50,254,189,2,86,8,8,253,41,8,137,1,51,123,68,15,8,153,35,77,5,174,197,72,90,251,87,16,253,207,7,123,8,8,5,115,123,254,63,122,25,75,155,56,16,0,1,0,24,0,1,4,185,5,33,0,32,0,0,37,16,2,35, +34,2,23,35,38,53,52,54,51,32,19,22,23,54,55,18,33,50,22,21,20,7,35,54,2,35,34,2,17,2,59,205,122,92,41,77,97,66,117,104,1,11,95,5,4,3,5,95,1,11,105,116,66,97,77,40,93,121,205,2,2,13,2,164,254,228,142,116,140,116,164,253,91,43,35,35,43,2,165,164,116,140, +116,142,1,28,253,92,253,243,0,2,0,53,255,248,4,156,4,196,0,8,0,46,0,0,1,34,6,20,22,50,54,52,38,39,54,55,62,2,51,21,34,2,7,6,7,22,23,22,21,20,6,35,34,38,53,52,55,54,55,38,39,38,2,35,53,50,30,1,23,22,2,104,113,158,158,225,159,157,114,100,58,66,74,124,141, +94,128,100,16,18,35,33,112,226,161,160,226,113,32,36,18,16,99,131,93,141,143,55,65,59,2,186,170,241,169,169,241,170,123,4,50,54,148,142,88,255,0,89,15,13,24,34,122,172,172,242,242,172,172,122,34,25,12,15,89,1,0,88,142,148,54,50,0,2,0,27,0,12,4,182,4, +206,0,19,0,25,0,0,1,38,39,53,4,32,37,21,6,7,17,22,23,21,36,32,5,53,54,63,1,54,23,17,6,39,1,46,136,139,1,26,2,106,1,23,143,135,135,143,254,233,253,150,254,230,139,136,124,189,189,189,189,4,25,18,42,120,73,73,122,39,19,252,168,19,38,124,74,74,120,44,17, +9,21,21,3,70,21,21,0,4,0,52,0,50,4,157,5,15,0,8,0,27,0,36,0,56,0,0,0,34,6,20,22,51,50,54,52,1,44,1,39,53,22,4,39,38,53,52,54,51,50,22,16,7,14,1,1,50,54,52,38,34,6,20,22,19,12,1,23,21,38,36,23,22,21,20,6,35,34,38,53,52,55,62,1,3,200,156,109,109,78,77, +109,254,169,255,0,254,213,125,207,1,201,9,108,168,121,122,169,85,60,202,254,22,77,110,110,154,110,109,234,1,1,1,43,125,207,254,55,9,108,168,121,122,169,85,60,201,2,131,124,178,124,124,178,254,44,1,38,40,117,79,31,35,101,156,138,194,194,254,237,97,72, +71,2,138,124,178,124,124,178,124,2,81,2,39,40,115,79,30,35,101,156,139,194,194,139,137,96,73,72,0,0,2,0,61,255,253,4,148,5,33,0,10,0,60,0,0,0,62,1,39,46,1,7,14,1,23,22,19,52,54,51,50,22,21,20,2,21,22,23,50,55,23,6,35,34,38,53,52,18,53,52,38,35,34,6,21, +20,22,23,30,1,7,6,7,6,38,39,38,53,52,55,54,55,54,23,54,38,1,68,132,57,25,26,130,66,66,56,26,26,205,196,158,151,192,255,3,118,63,87,58,112,98,87,126,252,144,116,112,132,41,22,32,14,34,45,102,102,201,41,20,24,45,103,116,112,21,81,1,64,51,131,65,65,58,26, +26,129,65,67,2,106,141,177,194,155,165,254,71,158,109,3,78,63,105,106,98,175,1,166,171,118,145,136,114,53,127,54,87,192,71,101,40,40,87,105,48,49,53,52,100,41,45,63,1,195,0,0,0,0,2,0,47,254,234,4,162,4,127,0,54,0,63,0,0,1,50,22,21,62,1,51,50,22,29,1, +62,1,51,50,22,21,16,5,20,23,35,38,39,6,7,53,54,55,39,17,54,39,14,1,7,17,35,17,52,38,7,38,6,7,17,35,17,52,39,51,22,23,62,1,1,17,54,19,52,38,7,34,6,1,193,45,83,29,139,53,44,57,34,92,48,43,70,254,244,103,118,33,52,117,124,135,87,6,2,34,41,94,44,107,22,25, +29,127,13,105,107,100,83,26,16,129,1,242,182,17,33,21,21,101,4,127,152,98,91,159,128,168,154,95,91,177,209,254,199,245,72,148,31,124,78,5,89,21,67,166,2,142,242,1,1,166,153,253,58,2,194,246,82,1,1,174,164,253,72,3,66,146,146,61,134,71,144,253,96,254, +83,191,1,3,148,110,4,158,0,0,2,0,85,0,181,4,124,4,234,0,3,0,35,0,0,19,33,21,33,1,33,53,51,38,53,52,54,51,50,22,21,20,7,33,21,33,53,35,54,55,54,53,52,38,34,6,21,20,23,22,23,85,4,39,251,217,1,140,254,116,252,48,183,132,132,184,48,1,20,254,90,1,13,12,61, +121,173,121,61,11,13,1,58,133,1,93,134,90,115,162,227,227,162,115,90,134,134,11,15,74,106,107,149,149,107,106,74,15,11,0,0,0,1,0,50,255,102,4,159,4,198,0,52,0,0,37,20,22,23,51,53,51,23,7,39,53,35,34,39,38,39,3,18,39,14,1,7,17,35,17,16,38,7,38,6,7,17, +35,17,52,39,51,22,23,62,1,51,50,22,21,62,1,51,50,22,29,1,17,3,89,69,59,60,2,136,136,2,60,135,45,30,5,14,2,33,38,89,42,100,21,24,27,120,13,99,102,95,79,24,15,122,46,42,79,27,132,50,41,55,226,90,101,1,96,141,142,3,96,98,60,96,2,129,1,1,1,1,176,163,253, +15,2,237,1,5,87,1,1,184,175,253,30,3,117,154,156,65,143,76,153,161,104,96,169,136,178,164,253,251,0,0,0,1,0,56,0,6,4,153,4,199,0,19,0,0,1,33,53,33,21,49,21,17,35,17,7,17,35,17,1,39,1,33,53,33,3,213,254,95,2,100,114,192,114,253,149,80,2,107,254,94,2,19, +4,75,123,85,1,253,190,1,199,209,253,190,1,198,253,95,87,2,161,123,0,2,0,21,0,3,4,188,4,207,0,39,0,47,0,0,1,50,18,55,54,51,50,22,21,20,6,35,34,39,14,1,7,35,53,55,54,19,38,2,35,34,2,23,7,52,2,39,53,50,22,23,54,55,62,1,1,22,51,50,55,38,39,34,2,50,88,67, +20,90,159,100,125,117,117,127,100,36,103,113,138,126,100,86,41,52,48,29,132,5,129,116,108,120,132,33,38,37,34,100,1,25,76,107,132,7,5,131,125,4,206,253,58,3,181,155,85,119,140,109,131,177,3,97,1,3,1,52,13,2,136,254,115,170,2,208,1,151,5,79,182,226,165, +72,75,123,252,215,119,162,129,15,0,2,0,89,1,64,4,120,3,174,0,32,0,65,0,0,19,54,51,50,23,22,55,54,51,50,23,22,55,54,51,50,23,7,38,7,6,34,39,38,7,6,35,34,39,38,6,35,39,17,54,51,50,23,22,55,54,50,23,22,55,54,51,50,23,7,38,7,6,35,34,39,38,7,6,35,34,39,38, +6,35,39,89,231,82,32,9,35,123,61,40,39,17,37,123,31,29,88,78,67,69,122,62,79,18,38,122,62,39,40,17,35,243,4,38,231,82,31,10,35,123,61,79,16,38,123,30,29,89,78,67,69,122,62,39,40,19,37,123,61,40,39,17,35,243,4,38,1,136,192,28,101,101,50,50,101,101,25, +224,36,201,108,54,54,107,100,50,51,100,201,69,1,80,192,28,100,100,51,51,100,100,25,224,36,202,108,55,54,107,100,51,52,101,202,69,0,0,1,0,94,0,5,4,115,5,35,0,28,0,0,1,7,2,3,7,0,19,33,53,33,2,1,23,18,19,51,18,19,55,0,3,33,7,33,18,1,39,2,3,2,210,211,28, +243,145,1,13,24,254,253,1,3,25,254,244,145,243,28,212,27,244,144,254,244,24,1,2,1,254,253,26,1,12,145,244,27,2,76,3,254,216,254,231,2,1,51,1,16,151,1,15,1,52,3,254,232,254,216,1,40,1,24,3,254,204,254,241,151,254,240,254,205,2,1,25,1,40,0,0,0,0,5,0,67, +0,5,4,142,4,128,0,15,0,32,0,36,0,84,0,100,0,0,1,54,55,38,39,38,34,14,1,21,20,22,23,22,23,33,51,33,54,55,62,1,53,52,46,1,35,34,7,6,7,22,23,1,21,33,53,1,17,38,39,46,1,53,52,62,1,51,50,23,53,52,54,55,54,55,53,35,53,51,53,51,21,51,21,35,21,22,23,30,1,29, +1,54,51,50,30,1,21,20,6,7,6,7,17,1,20,30,1,51,50,62,1,53,52,46,1,35,34,14,1,2,51,1,1,27,39,56,120,112,65,63,57,17,17,1,7,108,1,6,18,17,57,62,64,113,60,59,57,39,26,1,1,254,168,2,68,253,125,32,29,53,82,84,151,80,61,58,28,24,10,13,83,83,80,83,83,12,10,24, +28,59,60,80,151,84,82,52,30,32,254,88,19,35,17,19,34,19,19,34,19,17,35,19,2,234,3,2,33,21,32,62,114,62,62,112,30,11,6,6,11,30,112,62,62,114,62,32,21,33,2,3,254,65,232,232,254,219,1,37,10,17,41,150,82,83,151,81,24,2,27,49,13,6,3,41,54,66,66,54,41,3,6, +13,49,27,2,24,81,151,83,82,150,41,17,10,254,219,3,112,20,32,20,20,32,20,18,34,18,18,34,0,0,0,0,8,0,86,0,0,4,123,4,122,0,72,0,78,0,82,0,104,0,124,0,144,0,165,0,187,0,0,19,38,39,52,62,1,51,50,30,1,21,6,7,19,3,34,39,52,62,1,51,50,30,1,21,6,7,27,1,38,39, +52,62,1,51,50,30,1,21,6,7,27,1,38,53,52,62,1,51,50,30,1,21,6,7,3,19,38,53,52,62,1,51,50,30,1,21,6,35,3,17,33,17,5,53,7,33,39,29,2,33,53,1,23,3,54,55,62,1,53,52,46,1,35,34,14,1,21,20,30,1,51,50,51,19,23,3,54,55,62,1,52,46,1,35,34,14,1,20,30,1,51,50,51, +1,55,19,22,51,50,62,1,52,46,1,35,34,14,1,20,22,23,22,23,1,51,3,50,55,62,1,53,52,46,1,35,34,14,1,21,20,22,23,22,23,19,55,19,22,51,50,62,1,53,52,46,1,35,34,14,1,21,20,22,23,22,23,169,73,9,22,41,22,22,41,22,3,44,183,40,63,14,22,41,23,22,40,23,2,35,144,33, +51,1,23,40,21,22,41,23,3,51,29,142,36,23,41,21,23,41,22,8,66,71,197,33,23,40,22,23,40,22,10,75,123,253,109,2,103,138,254,234,140,2,44,253,180,59,177,5,5,14,16,16,27,15,14,26,17,16,27,14,6,6,238,104,143,4,4,13,15,15,27,14,15,27,15,15,27,15,5,6,1,73,88, +73,4,4,14,29,14,16,27,14,14,27,16,16,13,6,6,254,238,76,36,14,12,13,16,16,26,15,14,28,15,15,14,11,12,227,80,127,8,9,14,27,15,16,26,14,16,26,15,15,13,3,3,3,12,2,72,22,39,21,21,39,22,49,16,254,124,2,26,71,21,39,21,21,39,21,35,26,253,196,2,115,23,37,22,39, +20,20,39,22,41,19,253,139,2,55,36,32,21,39,21,21,39,21,65,12,253,236,1,138,27,32,22,39,21,21,39,22,72,254,158,254,84,1,172,221,172,57,46,161,37,126,126,1,4,32,1,147,2,3,8,27,14,16,26,16,16,26,16,14,27,15,254,114,24,2,70,2,2,8,27,29,27,15,15,27,29,27, +15,253,195,20,2,41,1,15,27,29,28,14,14,28,29,27,8,3,2,253,188,2,126,8,8,26,16,14,27,15,15,27,14,16,26,8,6,2,253,151,32,1,119,2,16,26,16,14,28,14,14,28,14,16,26,8,2,1,0,5,0,112,0,0,4,97,5,29,0,29,0,33,0,39,0,45,0,50,0,0,1,51,21,51,53,51,21,35,21,7,17, +23,21,51,21,33,53,51,53,55,51,17,35,39,53,35,53,51,21,51,1,53,33,21,1,55,53,33,21,23,17,7,21,33,53,39,53,17,55,33,17,1,237,242,150,236,101,80,80,101,252,15,101,81,1,1,81,101,232,149,2,68,252,112,2,225,72,253,62,72,64,2,178,65,1,253,206,5,29,136,136,142, +126,131,254,0,130,125,143,143,125,133,1,252,132,126,142,136,251,156,48,48,3,109,114,84,84,114,253,199,101,112,112,101,45,1,221,2,254,33,0,4,0,222,255,248,3,243,4,197,0,55,0,67,0,81,0,94,0,0,1,38,53,52,55,54,55,38,39,38,39,53,54,55,54,55,54,55,38,39,38, +53,52,62,1,51,50,30,1,21,20,7,6,7,22,23,22,23,22,23,21,6,7,6,7,22,23,22,21,20,7,6,7,19,33,27,1,53,51,53,35,53,35,21,35,21,51,21,19,54,53,52,46,1,34,14,1,21,20,23,3,33,0,20,30,1,50,62,1,52,46,1,35,34,6,1,194,25,26,6,9,49,29,34,1,1,34,35,64,23,24,21,14, +18,37,64,35,33,64,37,17,13,22,23,24,63,36,35,1,1,35,30,48,9,7,25,26,1,2,231,252,237,222,220,141,141,97,141,141,133,49,37,63,69,63,37,52,182,2,21,254,153,24,44,47,45,23,24,45,22,24,43,1,68,44,47,49,43,14,12,31,52,59,65,3,66,60,62,34,11,9,14,24,32,34,35, +62,34,34,62,35,34,32,24,15,8,11,34,62,60,66,3,65,59,51,32,12,14,43,49,48,44,3,3,254,188,1,75,1,18,102,89,101,101,89,102,254,238,37,60,35,64,34,34,64,35,52,45,254,233,4,47,48,43,23,23,43,48,43,23,23,0,0,0,0,4,0,144,0,6,4,65,4,199,0,30,0,42,0,51,0,86,0, +0,1,54,38,55,22,7,0,19,33,38,53,52,36,39,6,7,6,7,39,7,38,39,54,39,54,55,46,1,55,22,23,7,54,59,1,6,21,20,43,1,34,39,53,3,23,20,7,35,34,61,1,54,19,38,39,6,22,7,6,7,22,7,22,23,55,7,54,55,54,55,22,4,23,20,23,37,2,1,50,53,35,54,38,39,6,22,7,2,7,11,42,73,125, +32,1,142,37,252,235,10,1,71,7,73,46,37,128,8,35,113,26,74,12,39,59,17,10,31,84,44,132,31,78,4,35,56,17,6,3,5,5,58,8,23,33,176,29,62,35,49,20,48,36,17,73,20,84,78,28,110,23,86,66,44,254,165,2,9,2,199,31,254,110,1,3,32,17,63,37,35,15,4,3,20,78,97,106,105, +254,249,253,27,45,47,130,246,52,94,2,116,14,18,25,38,65,234,171,89,99,26,27,103,21,98,225,51,37,29,39,24,12,254,187,28,43,12,25,18,40,2,40,78,31,86,56,27,79,81,196,191,62,19,58,60,8,117,3,141,121,250,103,42,42,1,2,156,1,53,1,10,107,60,88,62,27,0,0,4, +0,156,0,6,4,53,4,104,0,13,0,29,0,80,0,91,0,0,0,20,30,1,51,50,62,1,52,46,1,35,34,6,55,20,30,1,51,50,62,1,53,52,46,1,35,34,14,1,1,21,33,53,7,38,53,52,54,55,54,55,38,39,38,53,52,54,55,54,55,38,39,38,52,62,1,51,50,30,1,20,7,6,7,22,23,30,1,21,20,7,6,7,22, +23,30,1,21,20,7,39,38,39,46,1,35,34,6,7,6,7,1,200,43,76,41,43,76,42,43,77,41,40,76,72,12,21,11,12,21,12,12,22,11,10,22,12,1,196,252,227,62,9,124,110,28,30,22,16,32,64,58,20,22,20,11,17,33,58,31,30,59,33,15,13,19,20,23,56,65,31,17,22,28,29,110,125,9,69, +3,48,52,184,96,97,183,51,48,3,2,216,84,76,42,42,76,84,77,40,40,202,12,20,11,11,20,12,11,22,12,12,22,252,13,1,1,1,43,43,120,220,58,16,12,21,29,56,62,62,113,31,11,7,15,21,30,63,57,32,32,57,63,30,21,15,7,11,31,113,62,62,56,29,21,12,16,58,220,120,43,43,99, +94,85,90,98,98,90,85,94,0,0,8,0,106,255,252,4,103,4,37,0,15,0,32,0,36,0,84,0,100,0,104,0,121,0,138,0,0,1,52,55,38,39,38,34,14,1,21,20,22,23,22,23,59,2,54,55,62,1,53,52,46,1,35,34,7,6,7,22,23,1,21,33,53,1,17,38,39,46,1,53,52,62,1,51,50,23,53,52,54,55, +54,55,53,35,53,51,53,51,21,51,21,35,21,22,23,30,1,29,1,54,51,50,30,1,21,20,6,7,6,7,17,1,20,30,1,51,50,62,1,53,52,46,1,35,34,14,1,1,21,33,53,55,35,38,39,46,1,53,52,62,1,51,50,23,22,23,6,21,51,52,39,54,55,54,51,50,30,1,21,20,6,7,6,7,35,2,55,2,25,36,53, +111,104,60,58,53,16,16,244,100,243,17,16,52,58,59,105,56,54,53,37,24,1,1,254,193,2,26,253,171,29,27,49,77,78,141,74,57,54,25,23,9,12,77,77,74,77,77,12,9,22,26,54,56,74,141,78,77,48,28,29,254,118,18,32,16,18,32,17,17,32,18,16,32,18,1,43,254,48,146,199, +13,12,43,47,48,85,45,44,44,29,21,2,172,2,21,29,43,44,46,84,49,47,44,12,13,198,2,172,2,3,30,20,29,57,106,57,58,104,28,10,6,6,10,28,104,58,57,106,57,29,20,30,3,2,254,97,215,215,254,240,1,16,9,16,38,140,76,77,140,75,22,1,26,45,13,5,2,39,50,61,61,50,39,2, +5,13,45,26,1,22,75,140,77,76,140,38,16,9,254,240,3,49,18,31,17,17,31,18,17,32,16,16,32,253,169,142,142,147,5,8,24,86,47,47,88,47,23,17,25,2,2,2,2,25,17,23,47,88,47,47,86,24,8,5,0,3,0,54,0,4,4,155,4,197,0,72,0,76,0,80,0,0,19,38,39,52,62,1,51,50,30,1,21, +6,7,19,3,34,39,52,62,1,51,50,30,1,21,6,7,27,1,38,39,52,62,1,51,50,30,1,21,6,7,27,1,38,53,52,62,1,51,50,30,1,21,6,7,3,19,38,53,52,62,1,51,50,30,1,21,6,35,3,17,33,17,5,53,33,21,5,53,33,21,141,77,10,24,44,23,23,44,23,4,46,194,42,67,15,23,44,25,23,43,23, +2,37,154,35,55,1,24,43,22,23,44,24,2,55,31,150,37,23,44,22,25,43,24,9,70,75,209,35,24,43,23,24,43,24,11,80,130,253,68,2,141,253,178,2,78,253,178,3,65,1,77,23,42,22,22,42,23,52,17,254,100,2,59,75,23,41,22,22,41,23,36,28,253,160,2,155,24,39,23,42,21,21, +42,23,44,19,253,100,2,89,38,34,22,42,22,22,42,22,69,13,253,204,1,163,27,35,23,42,22,22,42,23,76,254,136,254,58,1,198,165,63,63,242,64,64,0,0,0,0,4,0,148,0,5,4,61,4,197,0,3,0,7,0,37,0,41,0,0,1,53,33,21,1,53,33,21,19,51,21,51,53,51,21,35,21,7,17,23,21, +51,21,33,53,51,53,55,51,17,35,39,53,35,53,51,21,51,1,53,33,21,3,109,253,248,2,68,253,128,205,225,139,219,94,74,74,94,252,87,94,75,1,1,75,94,215,139,2,26,252,178,3,178,76,76,252,230,90,90,4,44,125,125,131,117,122,254,37,121,117,132,132,117,123,1,216,123, +117,131,125,251,235,45,45,0,0,0,0,2,0,226,0,6,3,239,4,199,0,52,0,64,0,0,1,52,55,54,55,38,39,38,39,53,54,55,54,55,54,55,38,39,38,53,52,62,1,51,50,30,1,21,20,7,6,7,22,23,22,23,22,23,21,6,7,6,7,22,23,22,21,20,7,19,33,19,38,55,53,51,53,35,53,35,21,35,21, +51,21,1,170,26,7,9,49,29,33,1,1,33,35,63,23,24,21,14,18,37,63,35,33,63,37,17,13,21,22,24,62,36,34,1,1,34,30,47,9,6,26,26,225,252,245,220,21,238,140,140,95,140,140,1,168,49,43,14,12,30,52,58,65,3,65,60,61,34,11,8,15,23,32,33,35,61,34,34,61,35,33,32,23, +16,7,11,34,61,60,65,3,65,58,51,31,12,14,43,49,47,43,254,185,1,72,43,228,101,88,101,101,88,101,0,0,0,0,4,0,103,0,2,4,106,5,32,0,34,0,46,0,55,0,61,0,0,1,54,38,55,30,1,7,51,20,35,0,19,33,38,53,52,0,39,6,39,6,39,55,7,38,39,54,39,54,55,54,38,55,22,23,7,21, +22,59,1,50,53,52,55,35,34,7,3,21,20,59,1,54,53,39,34,1,23,4,19,51,2,1,248,54,71,74,75,21,38,4,2,1,213,39,252,175,11,1,110,12,61,108,82,93,42,94,100,23,87,12,42,87,9,62,33,91,49,148,3,7,18,61,37,5,84,32,101,25,9,62,6,54,1,144,46,1,72,5,67,39,4,76,34,139, +39,71,128,13,1,254,215,252,225,49,50,140,1,0,104,152,6,132,4,91,70,25,72,229,184,96,91,36,37,111,23,107,223,14,26,43,29,42,56,254,100,21,25,13,46,30,1,248,78,235,253,99,2,232,0,0,1,0,118,0,5,4,91,4,198,0,46,0,0,55,38,53,52,54,55,54,55,38,39,38,53,52, +54,55,54,55,38,39,38,52,62,1,51,50,30,1,20,7,6,7,22,23,30,1,21,20,7,6,7,22,23,30,1,21,20,7,127,9,134,119,31,32,24,17,34,69,62,22,24,21,13,18,35,64,33,33,63,37,18,13,21,22,25,61,69,33,18,24,31,31,119,135,10,6,46,47,130,238,64,17,12,24,30,61,67,68,122, +34,12,8,15,24,31,69,62,34,34,62,69,31,24,16,7,12,34,122,68,67,61,30,24,13,16,64,238,130,47,46,0,0,1,0,128,0,133,4,81,5,79,0,35,0,0,1,22,23,22,23,22,29,1,20,7,6,35,34,39,35,21,20,23,35,53,54,53,39,35,7,6,35,34,47,1,53,52,55,0,63,1,2,107,77,177,195,5,32, +133,44,52,127,78,34,68,177,70,2,32,38,70,105,153,63,7,154,1,2,74,2,5,79,137,227,228,47,70,66,33,137,79,18,182,10,233,123,5,124,234,3,73,109,172,60,38,150,167,1,61,136,2,0,0,0,2,0,14,0,133,4,195,5,77,0,24,0,50,0,0,1,50,23,22,21,50,55,54,51,50,23,22,29, +1,20,7,0,7,35,1,38,53,52,55,54,3,21,20,23,1,51,1,54,61,1,52,39,38,35,34,3,6,21,35,52,39,38,35,34,7,6,1,61,179,96,23,5,10,93,193,172,100,31,182,254,142,50,5,254,13,99,164,66,188,171,1,134,3,1,216,85,155,59,47,217,71,8,5,59,83,156,143,88,30,5,77,226,66, +20,58,254,174,64,66,10,213,189,254,59,55,2,104,146,150,173,102,37,254,208,13,180,187,254,35,2,62,133,124,31,142,92,23,254,144,31,21,64,172,184,146,57,0,0,0,0,2,0,145,0,133,4,64,5,79,0,8,0,13,0,0,9,1,21,0,7,38,1,38,53,9,4,2,105,1,215,254,67,26,12,254, +110,58,1,213,254,94,1,165,1,166,254,168,5,79,253,158,5,253,185,28,9,2,14,71,10,2,32,253,222,253,219,2,37,1,189,0,0,1,0,50,0,133,4,159,5,79,0,55,0,0,1,50,23,22,23,20,15,1,51,54,59,1,50,23,22,21,20,7,6,7,34,39,35,21,16,23,21,35,39,54,17,53,35,6,35,34,39, +38,53,52,55,54,59,1,50,23,51,53,38,39,38,61,1,52,55,54,2,106,176,83,10,3,99,49,2,61,69,16,195,79,19,172,32,59,199,83,2,67,171,5,70,2,82,202,157,84,20,202,54,42,8,70,64,3,69,24,49,176,59,5,79,186,43,46,96,132,49,23,166,54,50,168,86,10,5,226,8,254,230, +89,5,5,105,1,18,2,228,166,56,47,192,68,10,23,2,59,56,91,66,12,165,86,15,0,0,0,0,3,0,127,0,134,4,82,5,80,0,34,0,60,0,66,0,0,1,22,1,22,29,1,20,7,6,43,1,34,39,35,21,20,23,35,53,54,53,35,7,6,43,1,34,39,38,53,55,53,52,55,18,55,6,1,6,21,22,23,22,59,1,50,55, +51,50,23,22,59,1,50,55,54,61,1,52,39,38,3,51,38,39,34,7,2,105,104,1,59,70,148,28,40,18,119,81,34,68,177,71,34,46,70,87,18,131,67,20,2,169,239,78,102,254,234,66,8,121,18,34,13,98,79,150,6,26,68,85,15,113,53,8,166,189,117,52,11,12,5,13,5,80,185,254,136, +114,111,2,172,64,13,179,11,230,127,5,124,239,83,96,143,54,52,11,2,164,175,1,39,60,164,254,183,107,110,153,44,7,179,58,121,137,33,25,25,145,170,236,252,64,19,74,68,0,0,0,1,0,11,0,133,4,198,5,79,0,23,0,0,1,50,23,22,23,51,54,55,54,51,50,23,22,21,20,7,1, +35,1,38,53,52,55,54,1,59,167,95,35,2,2,29,75,89,111,172,104,26,171,254,77,5,254,50,138,164,69,5,79,193,76,41,133,88,89,184,68,60,206,186,253,246,2,54,169,179,173,102,37,0,0,1,0,145,0,133,4,64,5,79,0,8,0,0,9,1,22,21,1,38,1,52,55,2,105,1,158,57,254,41, +10,254,50,92,5,79,253,231,69,11,253,159,6,2,91,11,114,0,0,3,0,49,0,134,4,160,5,86,0,50,0,96,0,103,0,0,1,50,23,22,21,20,15,1,54,59,1,50,23,22,21,20,7,6,7,34,39,35,21,16,23,21,35,39,54,17,53,35,6,35,34,39,38,53,52,55,54,59,1,50,23,38,39,53,52,55,54,3,20, +31,1,21,38,43,1,34,15,1,20,23,22,51,50,55,54,55,51,22,23,22,51,50,55,54,61,1,52,47,1,35,34,7,53,54,55,54,53,52,39,38,35,34,7,19,20,7,51,53,38,53,2,109,166,86,21,94,18,25,50,34,204,76,13,173,28,60,198,84,2,67,172,5,70,2,82,203,157,85,21,203,55,42,32,50, +25,81,23,177,59,198,139,10,88,97,7,200,50,6,112,50,64,173,94,13,18,6,30,68,74,130,138,70,10,208,44,5,97,88,106,26,21,153,45,33,152,68,216,23,50,23,5,86,169,57,47,109,136,19,5,177,46,48,173,82,10,6,227,7,254,228,90,4,4,106,1,19,3,230,167,57,47,194,67, +10,5,92,145,32,167,86,15,254,239,128,167,10,3,8,175,55,121,77,31,243,22,53,98,111,109,156,38,35,5,183,39,3,8,3,112,91,63,36,150,71,14,165,252,141,23,79,3,81,18,0,0,0,0,4,0,46,0,7,4,163,4,198,0,14,0,29,0,44,0,72,0,0,1,51,20,6,7,20,22,23,35,38,39,38,39, +38,54,37,51,20,6,7,20,22,23,35,38,39,38,39,38,54,5,51,20,6,7,20,22,23,35,38,39,38,39,38,54,19,30,1,21,20,6,4,32,36,38,53,52,54,55,51,6,7,6,20,30,1,32,62,1,52,39,38,39,1,126,11,118,1,165,6,11,23,133,39,12,4,138,1,5,11,119,2,167,5,11,23,132,40,12,3,138, +1,24,11,119,1,166,5,10,23,133,39,13,3,138,36,136,155,150,254,239,254,217,254,239,150,154,136,3,107,61,70,136,245,1,13,246,135,70,62,106,4,71,51,126,80,106,98,164,135,94,42,73,101,114,192,78,192,123,160,152,249,204,145,63,113,154,174,74,65,159,101,131, +125,206,169,118,54,92,126,144,254,120,40,143,79,78,143,80,80,143,78,79,143,40,33,56,63,136,124,69,69,124,136,63,56,33,0,0,1,1,114,0,33,3,95,5,170,0,17,0,0,1,51,23,17,20,15,1,35,34,47,1,52,63,1,50,23,51,17,3,21,68,6,185,45,33,200,26,4,199,31,93,85,4,5, +170,7,251,70,154,43,3,125,29,123,23,4,60,4,142,0,0,1,0,162,0,33,4,47,5,170,0,29,0,0,1,51,23,21,22,23,22,21,20,7,35,39,54,53,52,39,38,39,17,20,7,35,34,53,52,55,51,50,23,17,2,54,82,8,25,163,227,115,4,28,57,215,87,23,212,53,229,200,22,91,83,5,170,6,37,51, +59,66,131,137,91,30,47,79,66,67,39,25,252,18,144,42,158,124,21,60,4,144,0,1,0,106,255,95,4,103,5,165,0,30,0,0,1,5,23,17,20,7,35,34,61,1,52,63,1,50,23,17,37,17,20,15,1,35,34,61,1,52,63,1,50,23,17,1,217,2,140,2,181,51,201,167,37,81,77,253,251,142,63,25, +203,160,41,84,75,5,165,191,4,251,55,146,40,155,4,119,20,3,55,3,209,159,252,23,129,53,7,146,7,115,32,3,63,4,141,0,0,0,0,2,0,17,0,124,4,192,5,79,0,24,0,28,0,0,1,23,17,20,7,34,39,52,55,50,23,51,17,33,17,6,7,35,34,53,52,55,50,23,17,23,21,33,53,4,189,3,214, +192,15,192,89,65,3,253,62,7,199,3,212,194,82,72,73,2,194,5,79,3,251,243,176,17,135,113,12,49,2,32,253,211,171,29,145,103,13,52,4,2,170,128,128,0,0,0,0,2,1,68,0,37,3,141,5,174,0,12,0,19,0,0,1,51,23,17,51,54,51,22,23,2,5,39,17,19,17,36,17,54,39,34,1,73, +43,4,3,161,136,215,18,27,253,212,2,52,1,139,12,152,112,5,174,5,252,117,224,3,242,254,111,83,2,5,130,252,16,254,177,94,1,31,163,8,0,0,0,2,1,177,0,42,3,32,5,175,0,13,0,19,0,0,1,51,23,17,37,23,17,7,35,39,17,5,35,17,19,17,51,37,17,35,1,182,39,6,1,59,2,4, +38,5,254,194,2,50,1,1,13,2,5,175,5,254,73,152,2,251,166,5,5,1,202,151,4,72,253,188,254,147,135,1,106,0,0,0,0,2,1,55,0,42,3,154,5,175,0,40,0,44,0,0,1,51,23,17,55,23,21,6,7,17,55,21,6,7,17,7,35,39,17,5,17,7,35,39,17,7,53,52,55,17,35,7,53,55,17,55,51,23, +21,37,17,1,17,37,17,2,246,44,5,112,3,3,112,115,1,114,5,44,4,254,240,5,39,5,122,122,2,120,122,5,39,5,1,16,254,240,1,16,5,175,5,254,225,57,2,133,7,56,254,160,52,128,4,63,254,232,4,4,1,2,132,254,185,4,4,1,47,57,134,6,57,1,101,53,131,62,1,15,3,3,248,127, +1,58,253,185,254,156,131,1,95,0,0,1,0,96,255,254,4,113,5,28,0,69,0,0,1,35,38,7,35,34,39,53,54,53,52,39,53,54,55,51,22,59,1,53,52,39,53,54,55,51,22,50,55,51,22,23,21,6,29,1,51,50,55,51,22,23,21,6,21,20,23,21,6,43,1,38,7,35,17,20,23,21,6,7,35,38,34,7,35, +38,39,53,54,53,2,42,148,159,71,49,21,9,86,86,1,28,50,73,158,147,115,3,25,51,39,123,39,51,25,3,115,143,158,73,49,28,2,86,86,9,22,48,71,160,143,115,3,25,51,39,123,39,51,25,3,115,2,173,1,80,31,51,43,49,61,39,51,25,3,115,153,159,72,49,29,2,87,87,2,29,49, +72,159,153,115,3,25,51,39,61,49,43,51,31,80,1,254,136,159,72,50,28,2,87,87,2,28,50,72,159,0,0,0,6,0,46,255,240,4,163,5,15,0,6,0,13,0,20,0,27,0,59,0,71,0,0,19,6,7,22,23,55,53,5,21,23,54,55,38,39,1,38,39,6,7,23,51,3,35,7,22,23,54,55,3,51,55,22,23,6,7,39, +35,17,23,6,7,38,39,55,17,35,7,38,39,54,55,23,51,53,39,54,55,22,23,15,1,21,35,21,51,17,51,17,51,53,35,53,206,19,42,41,20,83,2,144,82,20,41,41,20,254,181,38,42,38,39,59,40,1,40,58,39,38,41,39,6,200,182,8,107,107,8,182,200,110,92,92,91,91,110,200,182,9, +107,107,9,182,200,110,91,91,92,92,110,96,102,102,47,101,101,3,46,40,40,38,40,59,40,1,40,58,40,38,40,40,1,64,20,41,41,20,83,252,200,83,20,42,42,20,2,152,110,92,93,91,91,111,254,132,182,10,106,106,10,182,1,124,111,91,92,92,92,110,187,183,10,106,106,10, +183,101,139,40,254,176,1,80,40,139,0,12,0,47,255,251,4,162,4,78,0,20,0,35,0,46,0,54,0,67,0,77,0,104,0,119,0,140,0,151,0,166,0,175,0,0,1,33,50,31,1,55,51,50,21,7,33,39,53,54,55,53,38,39,38,61,1,7,51,50,23,22,21,6,7,35,38,39,53,54,55,54,23,21,19,7,21,51, +55,7,38,47,1,5,23,55,38,43,1,34,7,5,22,31,1,21,20,7,6,43,1,38,39,53,31,1,51,50,63,1,52,47,1,6,37,51,50,23,22,21,7,35,39,6,15,1,23,7,35,38,39,38,61,1,52,63,1,35,39,53,55,23,21,23,51,21,20,7,21,22,23,19,51,23,53,39,5,51,23,21,33,50,55,51,23,21,6,7,6,43, +1,21,7,35,38,61,1,39,23,17,7,35,34,47,1,53,52,55,5,7,23,51,53,52,59,1,50,63,1,33,38,61,1,5,6,7,21,20,31,1,51,53,2,20,1,45,44,22,59,75,6,4,132,254,247,4,14,62,142,12,35,87,18,85,42,23,134,12,3,229,3,121,12,34,209,154,17,154,72,21,86,13,15,253,206,183, +122,47,59,21,64,34,2,191,14,113,4,61,17,28,111,9,137,41,119,101,41,28,1,36,73,173,253,197,15,7,89,39,4,4,76,137,11,3,4,5,2,17,132,15,65,15,2,76,4,97,14,2,88,1,119,152,2,21,72,1,229,4,3,1,27,32,27,2,4,5,149,19,26,149,3,7,131,62,6,4,227,88,37,4,67,1,201, +73,73,4,6,176,16,36,80,254,204,6,254,67,47,4,68,23,206,4,78,54,103,43,5,229,4,4,13,32,4,248,15,17,3,4,10,98,37,8,239,13,131,6,2,215,6,35,18,1,254,241,11,2,131,9,150,10,3,230,106,213,110,78,203,13,208,32,15,58,51,14,8,242,3,11,212,79,20,43,53,123,98,81, +164,60,10,4,44,235,26,16,30,4,21,229,20,23,6,21,100,31,45,4,4,29,4,10,2,6,150,8,20,193,1,9,6,3,131,229,4,88,25,4,1,16,255,22,93,3,220,10,3,136,5,254,247,3,102,29,9,39,94,9,131,130,6,22,74,137,1,15,6,22,74,28,7,65,33,4,211,0,0,4,0,60,0,10,4,149,4,56,0, +10,0,31,0,50,0,69,0,0,1,51,17,7,53,55,51,17,51,21,33,5,38,53,52,63,1,39,55,23,39,7,6,23,22,55,33,21,33,34,39,38,37,6,7,35,21,39,55,21,51,54,55,54,39,3,55,19,22,21,20,1,22,31,1,55,7,39,55,39,38,7,6,7,3,39,19,54,55,54,1,220,125,136,147,93,125,254,158,254, +129,32,28,61,45,171,18,45,72,15,27,29,87,1,40,254,159,55,42,33,4,11,62,128,121,154,154,144,42,19,18,49,147,99,177,27,253,189,123,70,61,46,18,171,44,72,28,45,46,39,148,100,176,29,40,35,1,89,1,43,19,71,22,254,139,67,134,56,57,53,55,106,26,78,187,26,125, +41,37,37,6,116,24,20,71,108,7,53,110,109,51,8,40,44,72,1,1,58,254,206,48,47,40,3,95,1,107,105,26,188,78,26,125,33,4,7,78,255,0,57,1,50,48,24,20,0,0,0,0,4,0,75,0,9,4,134,4,28,0,28,0,49,0,68,0,87,0,0,1,51,21,33,53,62,1,55,62,1,53,52,38,35,34,6,7,53,62, +1,51,50,22,21,20,6,7,14,1,5,38,53,52,63,1,39,55,23,39,7,6,23,22,55,33,21,33,34,39,38,37,6,7,35,21,39,55,21,51,54,55,54,47,1,55,19,22,21,20,1,22,31,1,55,7,39,55,39,38,7,6,15,1,39,19,54,55,54,2,64,242,254,137,46,146,17,35,26,53,42,34,73,63,54,79,34,91, +109,27,34,10,99,253,229,31,27,60,44,167,17,43,71,14,26,28,85,1,32,254,168,53,41,32,3,240,60,124,119,149,149,141,41,18,17,47,144,97,173,26,253,203,121,68,60,44,17,167,43,71,27,44,44,38,145,97,171,28,40,33,1,62,66,60,35,113,15,29,39,19,28,37,17,27,78,18, +14,71,57,27,49,32,9,77,232,55,56,51,53,104,26,76,183,26,123,39,36,36,5,113,24,19,69,104,8,51,107,106,50,8,39,43,71,250,56,254,214,47,46,38,3,72,1,103,104,26,183,76,25,123,32,5,6,76,250,56,1,42,47,23,19,0,0,0,4,0,68,0,10,4,141,4,42,0,40,0,61,0,80,0,99, +0,0,1,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,1,38,53,52,63,1,39,55,23,39,7,6,23,22,55,33,21,33,34,39,38,37,6,7,35,21,39,55,21,51,54,55,54,47,1,55,19,22,21,20,1,22,31,1,55,7,39,55, +39,38,7,6,15,1,39,19,54,55,54,2,246,8,68,124,113,37,78,50,52,72,39,67,66,61,57,80,83,51,52,54,52,30,69,62,54,79,35,93,111,60,253,107,32,28,60,45,170,17,44,71,15,26,29,86,1,36,254,164,54,41,34,3,254,61,126,120,152,152,142,42,18,18,48,146,98,175,27,253, +196,122,69,60,46,18,169,43,71,27,45,45,38,147,98,173,28,41,34,1,237,1,60,43,66,73,10,13,78,22,13,36,37,32,36,66,28,27,28,30,10,15,71,11,9,64,54,37,54,254,161,55,57,52,54,105,26,77,185,26,124,40,36,37,6,115,24,20,69,105,8,52,109,107,51,8,40,44,71,254, +57,254,210,48,46,39,3,83,1,105,105,26,185,77,26,123,33,5,6,77,253,56,1,47,47,23,20,0,5,0,36,0,7,4,173,4,100,0,2,0,13,0,34,0,53,0,72,0,0,1,7,51,3,51,17,51,21,35,21,35,53,33,53,1,38,53,52,63,1,39,55,23,39,7,6,23,22,55,33,21,33,34,39,38,37,6,7,35,21,39, +55,21,51,54,55,54,39,3,55,19,22,21,20,1,22,31,1,55,7,39,55,39,38,7,6,7,3,39,19,54,55,54,2,129,175,175,15,135,92,92,120,254,221,254,232,34,29,64,47,179,18,46,75,16,28,30,91,1,53,254,143,57,43,35,4,57,65,133,128,159,159,151,44,20,19,51,154,103,185,29,253, +163,128,74,64,48,19,179,46,75,29,48,48,40,155,104,184,29,43,36,2,119,196,1,44,254,212,72,109,109,73,254,222,59,60,55,57,111,28,81,196,28,131,43,38,39,6,121,25,21,74,112,8,55,115,113,53,8,42,47,75,1,12,60,254,193,50,50,41,3,133,1,111,111,28,196,81,27, +131,34,4,7,82,254,245,59,1,64,50,25,21,0,0,0,4,0,62,0,9,4,147,4,51,0,29,0,50,0,69,0,88,0,0,1,33,21,35,21,50,54,51,50,22,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,35,34,6,7,1,38,53,52,63,1,39,55,23,39,7,6,23,22,55,33,21,33,34,39,38,37,6,7,35,21,39, +55,21,51,54,55,54,39,3,55,19,22,21,20,1,22,31,1,55,7,39,55,39,38,7,6,15,1,39,19,54,55,54,1,202,1,72,230,4,31,17,101,118,121,110,36,76,50,55,67,39,60,67,67,60,28,59,50,254,149,32,27,61,45,171,18,45,72,14,26,29,87,1,39,254,160,55,41,34,4,9,62,128,121,153, +153,144,42,18,19,49,147,99,177,26,253,191,123,70,61,46,19,170,44,72,28,45,46,38,149,99,176,28,41,34,2,184,69,82,5,85,72,72,83,10,11,83,23,13,47,40,42,46,9,18,254,200,56,57,53,54,106,26,78,187,27,126,40,37,37,6,116,24,20,71,107,8,53,110,109,51,8,40,44, +72,1,0,58,254,207,48,48,39,3,92,1,106,105,26,187,78,25,125,33,4,7,78,255,57,1,49,47,24,20,0,0,0,5,0,75,0,0,4,134,4,18,0,9,0,34,0,55,0,74,0,93,0,0,1,34,6,20,22,51,50,54,52,38,55,21,46,1,35,34,6,7,6,54,51,50,22,21,20,6,35,34,38,53,52,54,51,50,22,1,38,53, +52,63,1,39,55,23,39,7,6,23,22,55,33,21,33,34,39,38,37,6,7,35,21,39,55,21,51,54,55,54,47,1,55,19,22,21,20,1,22,31,1,55,7,39,55,39,38,7,6,15,1,39,19,54,55,54,2,93,39,48,48,39,42,47,47,108,43,50,24,62,65,2,5,66,40,83,96,100,84,94,100,121,103,27,55,253,157, +31,27,60,44,167,17,43,71,14,26,28,85,1,32,254,168,53,41,32,3,240,60,124,119,149,149,141,41,18,17,47,144,97,173,26,253,203,121,68,60,44,17,167,43,71,27,44,44,38,145,97,171,28,40,33,1,219,46,84,45,45,84,46,192,72,15,10,68,38,5,29,82,69,67,83,117,107,102, +123,8,253,220,55,56,51,53,104,26,76,183,26,123,40,35,36,5,113,24,19,69,105,7,52,108,106,50,8,39,43,71,250,56,254,214,47,46,38,3,72,1,104,103,26,183,76,25,122,32,4,6,76,250,56,1,42,46,24,19,0,0,0,0,4,0,45,0,12,4,164,4,88,0,6,0,27,0,46,0,65,0,0,1,33,21, +3,35,19,33,1,38,53,52,63,1,39,55,23,39,7,6,23,22,55,33,21,33,34,39,38,37,6,7,35,21,39,55,21,51,54,55,54,39,3,55,19,22,21,20,1,22,31,1,55,7,39,55,39,38,7,6,7,3,39,19,54,55,54,1,178,1,129,204,110,191,254,250,254,156,33,29,63,47,177,18,46,74,15,27,30,89, +1,48,254,149,56,43,34,4,40,64,131,125,158,158,148,44,19,18,50,151,102,182,28,253,172,127,72,63,47,19,175,45,74,29,46,48,39,153,102,180,30,42,35,2,192,38,254,75,1,148,254,28,58,59,54,56,110,27,80,193,27,129,42,37,39,6,119,25,20,73,110,8,55,114,112,53, +8,41,46,74,1,8,60,254,198,50,49,40,3,118,1,109,109,27,193,81,26,129,34,5,7,80,254,249,59,1,58,49,25,20,0,0,3,0,45,0,0,4,164,4,75,0,20,0,39,0,58,0,0,55,38,53,52,63,1,39,55,23,39,7,6,23,22,55,33,21,33,34,39,38,37,6,7,35,21,39,55,21,51,54,55,54,39,3,55, +19,22,21,20,1,22,31,1,55,7,39,55,39,38,7,6,7,3,39,19,54,55,54,78,33,29,63,47,177,18,46,74,15,27,30,89,1,48,254,149,56,43,34,4,40,64,131,125,158,158,148,44,19,18,50,151,102,182,28,253,172,127,72,63,47,19,175,45,74,29,46,48,39,153,102,180,30,42,35,136, +58,60,54,56,109,27,80,192,27,129,42,38,38,6,119,25,20,72,110,7,55,113,112,53,9,41,46,74,1,8,59,254,198,49,49,41,3,119,1,110,108,27,193,80,26,130,33,4,7,80,254,248,59,1,59,49,25,20,0,6,0,57,255,255,4,152,4,57,0,16,0,26,0,39,0,57,0,72,0,82,0,0,1,33,50, +31,1,55,51,21,6,7,33,53,54,55,3,38,35,7,50,31,1,7,38,39,54,55,54,1,22,21,23,20,7,6,43,1,38,39,54,55,5,22,23,39,6,15,1,23,35,3,39,54,55,54,53,39,53,51,1,51,21,33,50,55,51,20,3,6,43,1,21,35,47,1,23,17,7,35,34,47,1,52,55,2,24,1,36,44,25,55,74,5,118,12,254, +255,73,3,148,26,10,77,79,32,36,144,201,20,112,16,37,2,132,124,2,73,11,30,94,11,131,18,151,253,91,128,1,84,144,3,2,4,4,151,6,3,60,20,75,171,2,34,1,1,40,25,22,2,150,18,24,153,3,126,71,4,4,217,87,36,3,63,4,56,63,93,41,2,206,16,4,40,7,1,9,19,3,69,65,247, +115,15,194,22,35,254,192,208,17,30,76,44,6,12,235,17,84,20,216,10,48,248,12,31,21,1,4,24,24,96,30,9,43,2,254,252,87,20,7,254,251,17,86,219,132,4,254,255,4,96,36,36,97,0,0,0,0,7,0,46,0,7,4,163,4,124,0,19,0,37,0,50,0,60,0,74,0,92,0,101,0,0,1,51,32,19,22, +29,1,16,5,6,43,1,32,3,38,61,1,16,55,54,23,21,50,31,1,21,6,7,21,51,54,55,35,7,38,39,38,35,5,22,51,54,55,38,35,38,35,34,7,6,7,5,21,23,51,50,55,52,47,1,34,5,23,6,7,20,31,1,51,52,63,1,51,23,39,5,7,22,23,51,53,55,51,50,63,1,53,35,6,43,1,39,53,5,6,29,1,20, +31,1,51,53,2,94,21,1,45,185,74,254,206,124,139,3,254,183,176,64,241,145,104,29,39,92,20,45,214,7,101,2,64,60,14,16,19,254,30,185,6,3,114,50,18,22,38,72,41,59,10,1,232,117,90,74,20,77,31,11,252,205,61,57,8,106,22,2,21,108,7,58,106,1,128,103,5,98,3,4,131, +28,46,81,2,17,26,241,4,254,105,50,81,20,192,4,124,254,233,133,157,5,254,182,179,58,1,42,127,125,40,1,11,184,100,112,2,82,157,2,17,24,2,6,183,33,104,17,9,220,106,11,196,96,14,93,95,23,169,3,204,105,36,120,58,45,40,94,37,17,177,44,51,19,189,34,184,216, +191,2,180,69,5,97,135,2,12,5,72,77,80,30,9,69,31,3,222,0,0,0,0,8,0,55,0,4,4,154,4,103,0,15,0,32,0,47,0,58,0,66,0,82,0,96,0,106,0,0,1,32,19,22,21,16,5,6,35,32,3,38,53,16,37,54,1,16,5,22,59,1,32,19,54,53,16,37,38,35,32,3,6,1,51,50,31,1,55,21,6,7,35,53, +55,38,47,1,35,50,31,1,7,35,38,39,54,55,54,1,22,29,1,6,43,1,39,37,51,23,7,35,39,35,6,7,21,38,47,1,52,55,39,5,51,21,51,50,55,21,15,1,35,7,21,35,39,37,51,23,21,7,35,34,47,1,54,2,106,1,49,178,77,254,227,123,157,254,199,174,71,1,38,128,254,122,1,10,118,127, +36,1,14,172,69,254,240,120,138,254,221,168,69,1,197,235,40,18,43,61,82,20,204,58,110,19,20,58,68,23,33,115,2,171,13,89,21,33,1,250,103,16,81,75,117,253,162,207,109,2,2,59,2,125,4,9,117,2,65,59,2,62,5,245,15,18,130,17,127,4,5,101,254,231,225,4,4,184,61, +29,5,1,4,103,254,241,134,158,254,194,175,67,1,23,121,165,1,63,176,63,253,205,254,212,162,66,1,3,124,147,1,42,168,62,254,252,119,1,18,52,73,32,2,153,26,2,39,191,29,9,53,64,194,96,12,160,19,24,254,253,169,25,17,98,199,67,183,2,36,208,16,20,9,205,13,21, +106,36,206,72,15,4,219,7,5,63,178,105,4,207,4,77,33,37,0,5,0,46,0,7,4,163,4,124,0,7,0,23,0,31,0,55,0,72,0,0,1,22,23,50,55,38,39,6,1,32,19,22,21,16,5,6,35,32,3,38,53,16,37,54,1,6,7,22,51,54,55,38,5,21,35,6,39,46,1,55,38,54,55,50,23,54,51,30,1,7,22,6,7, +6,39,35,37,16,5,22,59,1,32,19,54,53,16,37,38,35,32,3,6,1,4,1,140,109,74,66,124,133,1,101,1,54,180,79,254,222,125,159,254,194,176,73,1,43,129,1,111,124,66,74,110,139,2,2,254,155,2,94,143,106,97,5,3,121,103,119,97,97,121,103,120,2,4,97,106,143,94,2,253, +229,1,14,119,130,36,1,19,174,70,254,236,121,141,254,216,170,70,2,71,156,2,155,148,3,2,1,162,254,237,135,162,254,189,177,68,1,28,123,167,1,67,180,63,254,96,3,148,155,2,156,146,205,22,150,6,12,147,66,93,119,1,130,130,1,119,93,66,147,12,6,150,74,254,208, +165,67,1,7,125,150,1,46,171,63,254,248,121,0,0,2,0,80,0,8,4,129,5,37,0,24,0,46,0,0,1,50,21,6,7,23,51,50,23,7,35,23,33,22,19,55,23,6,7,38,3,33,34,3,52,1,6,35,34,46,1,53,52,55,54,55,23,6,7,20,30,1,50,54,55,23,6,1,140,134,1,112,21,241,11,14,4,241,11,1,133, +11,123,117,42,4,240,14,130,254,95,11,74,1,185,99,108,108,198,109,56,28,42,35,22,2,73,133,145,132,37,60,40,5,36,124,143,1,202,128,3,88,6,254,164,35,123,7,78,21,1,119,2,192,116,251,27,55,109,197,110,108,100,52,41,190,53,58,73,133,73,73,66,147,44,0,0,3, +0,60,0,5,4,149,4,95,0,23,0,27,0,31,0,0,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,17,33,17,37,33,17,33,1,255,14,16,23,20,32,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,254,62,4,87,252,36,3,96,252,160,2,52,31,21,23,16,14,14, +16,23,20,32,32,21,22,16,14,14,15,23,21,253,241,4,90,251,166,124,3,98,0,4,0,60,0,5,4,149,4,95,0,23,0,47,0,51,0,55,0,0,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38, +1,17,33,17,37,33,17,33,1,23,14,16,23,20,32,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,1,209,14,15,23,21,32,31,21,23,16,14,14,16,23,20,32,32,21,22,16,14,253,85,4,87,252,36,3,96,252,160,1,72,31,21,23,15,14,14,15,23,21,31,32,21,23,15,15,15,15,23,21,1, +244,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,14,16,23,20,253,9,4,90,251,166,124,3,98,0,0,0,0,5,0,60,0,5,4,149,4,95,0,23,0,47,0,71,0,75,0,79,0,0,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,19,52,55,54,55,54,51,50,23,22,23,22, +21,20,7,6,7,6,35,34,39,38,39,38,19,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,17,33,17,37,33,17,33,1,23,14,16,23,20,32,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,232,14,16,23,20,32,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14, +233,14,15,23,21,32,31,21,23,16,14,14,16,23,20,32,32,21,22,16,14,253,85,4,87,252,36,3,96,252,160,1,72,31,21,23,15,14,14,15,23,21,31,32,21,23,15,15,15,15,23,21,1,12,31,21,23,16,14,14,16,23,20,32,32,21,22,16,14,14,15,23,21,1,8,32,21,22,16,14,14,15,23,21, +32,31,21,23,16,14,14,16,23,20,253,9,4,90,251,166,124,3,98,0,6,0,60,0,1,4,149,4,91,0,23,0,47,0,71,0,95,0,99,0,103,0,0,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38, +37,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,17,33,17,37,33,17,33,1,23,14,16,23,20,32,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,1,209,14,15,23,21,32,31,21, +23,16,14,14,16,23,20,32,32,21,22,16,14,254,47,14,16,23,20,32,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,1,209,14,15,23,21,32,31,21,23,16,14,14,16,23,20,32,32,21,22,16,14,253,85,4,87,252,36,3,96,252,160,3,24,32,21,23,15,15,15,15,23,21,32,31,21,23,15, +14,14,15,23,21,254,75,31,21,23,16,14,14,16,23,20,32,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,14,16,23,20,32,32,21,22,16,14,14,15,23,21,1,244,32,21,23,15,15,15,15,23,21,32,31,21,23,15,14,14,15,23,21,253,8,4,90,251,166,124,3,98,0,0,0,7,0,60,0,5,4,149, +4,95,0,23,0,47,0,71,0,95,0,119,0,123,0,127,0,0,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,37,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1, +52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,7,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,17,33,17,37,33,17,33,1,23,14,16,23,20,32,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,1,209,14,15,23,21,32,31,21,23, +16,14,14,16,23,20,32,32,21,22,16,14,254,47,14,16,23,20,32,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,1,209,14,15,23,21,32,31,21,23,16,14,14,16,23,20,32,32,21,22,16,14,233,14,16,23,20,32,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,254,62,4,87,252,36, +3,96,252,160,3,28,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,14,16,23,20,254,76,31,21,23,15,14,14,15,23,21,31,32,21,23,15,15,15,15,23,21,32,31,21,23,15,14,14,15,23,21,31,32,21,23,15,15,15,15,23,21,1,244,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14, +14,16,23,20,200,31,21,23,16,14,14,16,23,20,32,32,21,22,16,14,14,15,23,21,253,241,4,90,251,166,124,3,98,0,0,0,0,8,0,60,255,252,4,149,4,86,0,23,0,47,0,71,0,95,0,119,0,143,0,147,0,151,0,0,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38, +37,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,17,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,37,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7, +6,35,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,17,33,17,37,33,17,33,2,231,14,16,23,20,32,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,254,48,14,15,24,20,32,32,20,23,16,14,14,15,24,20,32,32,20,23,16,14,14,16,23, +20,32,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,1,209,14,15,23,21,32,31,21,23,16,14,14,16,23,20,32,32,21,22,16,14,254,47,14,16,23,20,32,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,1,209,14,15,23,21,32,31,21,23,16,14,14,16,23,20,32,32,21,22,16,14, +253,85,4,87,252,36,3,96,252,160,2,43,32,21,22,16,14,14,15,23,21,32,32,21,22,16,14,14,15,23,21,32,32,21,22,16,14,14,15,23,21,32,32,21,22,16,14,14,15,23,21,1,46,32,21,22,16,14,14,15,23,21,32,32,21,22,16,14,14,15,23,21,254,0,32,21,22,16,14,14,15,23,21,32, +31,21,23,16,14,14,16,23,20,32,32,21,22,16,14,14,15,23,21,32,31,21,23,16,14,14,16,23,20,2,64,32,21,22,16,14,14,15,23,21,32,32,21,22,16,14,14,15,23,21,252,227,4,90,251,166,124,3,98,0,0,0,0,3,0,46,0,0,4,163,4,116,0,12,0,27,0,41,0,0,1,50,4,18,16,2,4,32,36, +2,16,18,36,1,20,30,1,32,62,1,53,52,46,1,35,34,14,1,4,52,62,1,51,50,30,1,20,14,1,35,34,38,2,104,144,1,16,154,150,254,240,254,217,254,240,150,153,1,16,254,152,133,240,1,7,240,133,137,240,128,127,242,135,2,185,26,46,25,24,46,26,27,45,24,25,45,4,116,147, +254,238,254,214,254,242,151,151,1,14,1,42,1,18,147,253,198,132,240,132,132,240,132,131,243,130,130,243,156,50,46,25,25,46,50,47,24,24,0,0,0,0,4,0,46,0,5,4,163,4,121,0,12,0,27,0,41,0,54,0,0,1,50,4,18,16,2,4,32,36,2,16,18,36,1,20,30,1,32,62,1,53,52,46, +1,35,34,14,1,4,52,62,1,51,50,30,1,20,14,1,35,34,38,36,50,30,1,20,14,1,35,34,46,1,52,54,2,104,144,1,16,154,150,254,240,254,217,254,240,150,153,1,16,254,152,133,240,1,7,240,133,137,240,128,127,242,135,2,185,26,46,25,24,46,26,27,45,24,25,45,253,230,49,46, +26,26,45,26,24,46,26,27,4,121,147,254,238,254,214,254,242,151,151,1,14,1,42,1,18,147,253,198,132,240,132,132,240,132,131,243,130,130,243,156,50,46,25,25,46,50,47,24,24,168,24,47,50,46,25,25,46,50,47,0,0,0,2,0,46,0,0,4,163,4,116,0,12,0,26,0,0,1,50,4,18, +16,2,4,32,36,2,16,18,36,1,50,62,1,52,46,1,35,34,14,1,20,30,1,2,104,144,1,16,154,150,254,240,254,217,254,240,150,153,1,16,1,178,24,45,27,26,46,24,25,46,26,27,45,4,116,147,254,238,254,214,254,242,151,151,1,14,1,42,1,18,147,253,102,24,47,50,46,25,25,46, +50,47,24,0,0,3,0,46,255,246,4,163,4,106,0,12,0,26,0,39,0,0,1,50,4,18,16,2,4,32,36,2,16,18,36,1,50,62,1,52,46,1,35,34,14,1,20,30,1,36,20,30,1,51,50,62,1,52,46,1,34,6,2,104,144,1,16,154,150,254,240,254,217,254,240,150,153,1,16,1,178,24,45,27,26,46,24,25, +46,26,27,45,253,113,26,46,24,26,45,26,26,46,49,45,4,106,147,254,238,254,214,254,242,151,151,1,14,1,42,1,18,147,253,102,24,47,50,46,25,25,46,50,47,24,121,50,46,25,25,46,50,47,24,24,0,1,0,82,0,7,4,127,0,150,0,3,0,0,55,33,21,33,82,4,45,251,211,150,143,0, +0,0,0,2,0,82,0,7,4,127,0,150,0,3,0,7,0,0,55,33,21,33,37,33,21,33,82,1,179,254,77,2,122,1,179,254,77,150,143,143,143,0,0,2,0,150,255,254,4,59,4,187,0,9,0,26,0,0,1,54,4,55,17,6,39,38,7,47,1,35,39,51,21,35,21,54,23,22,55,17,6,36,7,17,35,1,37,135,1,128,215, +175,190,143,210,16,80,61,1,219,61,205,176,204,188,231,254,98,146,78,2,27,43,187,35,1,240,33,102,129,34,2,75,43,43,21,33,124,111,53,253,155,60,201,63,254,49,0,0,1,0,115,0,5,4,94,5,30,0,16,0,0,19,35,39,51,21,35,21,54,23,22,55,17,6,36,7,17,35,182,66,1,236, +66,221,189,220,203,249,254,66,157,84,4,240,46,46,23,35,133,120,58,253,107,65,217,68,254,13,0,0,0,0,1,0,39,255,255,4,170,4,40,0,31,0,0,1,39,7,39,55,39,55,23,55,23,7,23,55,39,55,23,55,23,7,22,19,39,7,31,1,7,47,1,15,1,39,55,2,37,237,132,140,132,33,98,31, +131,140,130,236,237,131,141,131,31,97,32,50,24,214,236,126,227,131,192,128,126,192,131,225,1,196,239,132,141,133,31,98,31,132,142,132,239,238,133,142,133,32,98,31,80,254,230,220,240,127,193,132,228,127,127,228,132,193,0,0,0,0,2,0,31,0,0,4,178,4,211,0, +15,0,82,0,0,1,20,30,1,51,50,62,1,53,52,46,1,35,34,14,1,19,21,35,6,35,34,39,53,35,21,35,34,38,39,38,39,7,3,23,7,48,23,22,23,22,23,17,33,53,33,53,38,39,46,1,52,62,1,51,50,30,1,20,6,7,6,7,21,33,21,33,17,54,55,54,55,54,55,39,55,3,39,6,7,6,7,6,1,252,32,58, +31,33,57,33,34,57,32,30,58,33,184,6,30,32,2,3,5,6,137,251,70,13,11,71,23,249,70,5,59,107,89,95,254,207,1,49,21,21,50,55,56,101,53,54,100,58,56,49,22,22,1,41,254,215,82,76,107,60,2,3,71,250,24,71,10,14,69,126,94,3,255,32,58,32,32,58,32,32,59,32,32,59, +251,229,1,2,1,1,1,78,71,14,13,53,1,13,101,52,5,71,40,32,6,2,76,105,41,7,11,28,101,110,102,55,55,102,110,101,28,11,7,41,105,253,182,9,27,40,71,3,2,52,101,254,243,53,13,14,71,40,29,0,4,0,129,0,12,4,80,4,109,0,4,0,9,0,57,0,89,0,0,37,38,39,7,22,37,23,54, +55,38,1,23,54,55,51,6,7,23,22,23,14,1,7,38,47,1,6,7,39,54,55,39,7,22,23,7,38,39,7,6,7,34,38,39,52,63,1,38,39,51,22,23,55,1,39,9,1,7,1,21,39,1,55,9,1,23,1,3,38,47,1,30,1,23,55,38,39,19,23,35,23,6,7,23,62,1,55,7,6,7,4,14,36,15,7,3,252,177,6,15,37,56,2, +24,208,56,20,69,19,70,117,47,1,4,45,32,54,3,117,78,68,29,76,50,183,182,50,76,29,69,78,117,1,47,30,56,3,48,117,70,19,68,21,56,209,254,106,24,1,230,1,231,25,254,85,24,1,189,4,254,52,254,53,3,1,191,239,66,37,17,31,121,133,6,92,65,234,27,1,204,64,89,7,132, +121,31,16,36,70,24,10,48,6,61,47,6,48,10,9,1,159,228,44,45,88,55,136,2,48,32,25,1,3,59,126,42,6,50,12,37,218,218,37,12,50,6,42,126,54,8,22,27,57,2,136,55,88,45,44,228,1,227,111,253,236,2,20,111,254,3,1,27,2,16,11,253,242,2,14,11,253,244,254,243,43,70, +1,57,100,49,12,28,41,1,12,30,240,40,27,12,49,100,57,1,67,49,0,0,0,5,0,188,255,253,4,21,5,236,0,3,0,22,0,42,0,67,0,84,0,0,1,22,39,38,19,21,6,35,34,39,53,38,55,54,55,21,6,21,6,4,7,35,38,3,36,39,38,37,21,6,21,20,4,23,6,5,39,54,39,38,39,17,39,19,17,39,17, +36,39,54,55,54,23,7,23,6,39,38,7,6,4,23,6,5,53,36,39,54,37,39,3,46,1,53,52,62,1,51,50,30,1,21,20,6,7,1,148,68,22,36,250,12,28,34,4,182,2,6,158,64,4,1,70,2,14,28,198,254,232,6,2,1,16,170,2,44,2,4,254,238,2,188,6,2,194,78,78,78,254,118,4,14,212,70,56,112, +94,76,98,50,10,4,2,242,6,6,254,150,1,18,2,12,254,216,78,4,22,24,24,42,22,24,42,24,24,20,4,181,30,43,11,251,148,66,29,64,48,34,65,82,25,47,24,22,48,63,119,65,1,183,37,111,100,47,68,38,51,46,89,97,81,47,53,35,51,36,34,254,180,19,3,1,254,129,16,1,117,19, +138,144,5,4,73,30,25,18,39,13,64,51,47,117,138,16,61,32,61,35,110,7,1,45,11,46,24,25,46,24,24,46,25,24,46,11,0,3,0,19,0,3,4,190,4,119,0,3,0,7,0,51,0,0,37,11,1,22,37,11,1,22,1,51,50,29,1,20,43,1,19,6,7,14,1,35,34,46,1,55,19,33,19,22,14,1,34,38,39,38,39, +19,35,38,61,1,52,59,1,55,23,51,55,23,51,55,4,128,207,207,207,254,68,207,207,207,2,175,160,42,31,145,207,2,36,35,130,71,70,129,72,2,204,253,250,205,2,72,129,141,130,37,35,1,206,153,24,43,161,40,38,189,97,97,189,39,196,2,109,253,147,57,57,2,109,253,147, +57,2,249,32,18,30,253,149,51,46,48,53,53,95,52,2,105,253,151,52,95,53,53,48,46,51,2,107,12,22,11,35,116,116,242,242,116,0,2,0,22,0,6,4,187,4,107,0,22,0,34,0,0,1,54,51,50,23,22,23,22,21,20,7,6,7,6,38,39,46,1,7,6,7,39,18,1,19,35,3,35,17,35,3,35,3,35,19, +1,214,138,118,41,37,151,56,27,13,32,95,94,168,62,25,58,107,123,149,90,172,3,178,71,95,63,215,103,1,214,64,96,72,4,44,62,6,30,124,58,61,43,44,106,44,44,60,134,54,79,47,50,217,51,1,51,254,29,254,60,1,98,254,158,1,98,254,158,1,196,0,0,0,2,0,74,255,253,4, +135,5,30,0,13,0,49,0,0,0,20,30,1,51,50,62,1,52,46,1,35,34,6,19,21,51,22,54,55,20,4,7,6,7,35,38,55,38,36,3,30,1,55,51,53,38,39,46,1,52,62,1,50,30,1,20,6,7,6,1,207,44,80,42,43,80,44,46,78,43,41,80,164,5,133,198,151,254,100,34,47,1,37,40,2,4,254,77,77,174, +216,126,6,57,53,68,76,77,137,145,139,78,77,68,50,4,41,87,78,44,44,78,87,80,42,42,254,103,136,1,168,33,202,135,132,119,214,156,143,115,126,1,10,1,215,12,135,6,31,38,136,151,138,74,74,138,151,136,38,28,0,0,0,0,3,0,30,0,0,4,179,4,211,0,63,0,71,0,79,0,0, +0,50,31,1,22,23,55,22,23,7,22,23,55,22,23,7,22,20,7,23,6,7,39,6,7,23,6,7,39,6,15,1,6,34,47,1,38,39,7,38,39,55,38,39,7,38,39,55,38,52,55,39,54,55,23,54,55,39,54,55,23,54,63,1,18,32,6,16,22,32,54,16,6,20,6,34,38,52,54,50,2,69,71,35,26,57,54,92,62,52,50, +40,28,112,30,13,95,4,4,95,13,30,112,28,40,50,52,62,92,54,57,26,35,71,35,26,58,53,92,62,52,50,40,28,112,30,13,95,4,4,95,13,30,112,28,40,50,52,62,92,53,58,26,218,254,217,209,209,1,39,209,224,78,109,78,78,109,4,211,4,128,11,25,85,37,52,109,43,51,13,69,74, +53,30,58,29,54,74,69,13,51,43,109,52,37,84,24,12,127,5,5,127,12,24,84,37,52,109,43,51,13,69,74,54,29,58,30,53,74,69,13,51,44,108,52,37,84,24,11,128,255,0,210,254,217,208,208,1,39,92,110,77,77,110,77,0,0,0,0,15,0,42,0,12,4,167,5,63,0,8,0,13,0,18,0,23, +0,28,0,33,0,38,0,43,0,48,0,53,0,58,0,63,0,68,0,80,0,145,0,0,0,20,30,1,51,38,55,34,6,5,22,23,55,38,39,22,23,55,38,39,22,23,55,38,39,22,7,55,38,39,22,7,23,54,39,6,7,23,54,37,23,54,55,6,7,23,54,55,6,7,23,54,55,6,31,1,38,55,6,23,55,38,55,6,23,55,38,39,6, +23,34,6,21,20,22,51,50,54,53,52,38,39,53,38,39,46,1,52,62,1,51,50,30,1,20,6,7,6,7,51,20,35,21,22,23,22,23,54,55,4,23,6,35,38,7,22,21,20,7,6,7,3,21,6,35,34,39,53,3,38,39,38,53,52,55,38,7,34,39,54,37,22,23,54,55,54,2,49,15,27,16,26,26,15,28,1,180,97,36, +23,79,127,96,32,34,78,105,66,14,42,52,108,44,1,52,34,85,2,21,52,2,55,41,44,51,40,252,224,23,36,97,77,35,34,31,97,84,17,42,14,66,70,13,52,1,44,61,52,52,22,3,35,89,51,44,41,6,253,48,66,66,48,47,67,66,79,3,2,16,19,19,34,18,18,33,19,18,17,1,3,1,1,45,36,3, +3,70,19,1,36,70,74,223,70,49,4,46,35,45,1,10,20,22,7,2,45,35,45,2,50,77,223,74,70,1,36,19,71,6,8,35,5,9,30,27,16,56,60,15,103,55,42,33,50,17,85,54,29,74,37,110,61,17,95,67,127,66,7,110,84,135,62,9,114,89,119,48,23,100,9,34,42,55,14,93,29,54,85,36,117, +17,61,110,59,119,7,66,127,76,122,9,62,135,92,101,23,48,119,90,51,67,46,49,66,66,49,46,67,40,78,1,2,9,34,37,34,18,18,34,37,34,9,2,1,1,77,8,35,3,3,112,46,5,80,143,22,22,17,18,65,46,36,7,253,59,81,19,25,87,2,185,7,36,46,65,15,15,28,23,142,80,5,45,123,9, +8,34,0,0,15,0,82,0,11,4,127,4,199,0,15,0,26,0,38,0,46,0,70,0,82,0,138,0,150,0,158,0,166,0,178,0,186,0,194,0,202,0,214,0,0,1,50,30,1,21,20,14,1,35,34,46,1,53,52,62,1,7,38,39,6,7,6,22,55,54,55,38,37,6,7,22,23,22,55,54,39,38,39,6,39,22,21,20,7,54,55,38, +39,38,39,38,39,6,7,6,7,6,21,20,23,22,23,22,23,54,55,54,55,54,53,52,55,22,23,22,23,54,55,54,39,38,7,6,5,55,62,1,51,50,22,23,21,54,23,22,23,22,21,20,7,6,7,51,22,23,22,21,20,7,14,1,39,35,6,7,6,35,34,39,38,39,6,38,39,38,53,52,55,54,55,38,39,38,53,52,55,54, +55,54,5,38,39,38,35,34,7,6,7,22,23,54,23,6,7,22,23,22,23,38,37,6,7,54,55,54,55,38,39,38,39,38,7,6,23,22,23,54,55,54,7,6,7,22,23,38,53,52,23,22,23,54,55,38,39,38,23,22,23,54,55,6,7,6,7,6,7,22,23,22,51,50,55,54,55,38,2,104,16,29,16,16,29,16,16,29,16,16, +29,183,64,57,104,41,44,41,82,80,124,12,1,136,5,11,124,80,82,21,21,45,42,103,58,62,2,2,47,42,42,89,38,40,41,40,40,39,41,38,1,1,38,41,39,41,40,40,41,37,3,20,12,5,64,57,102,43,46,21,21,84,82,254,34,1,28,96,51,51,96,27,138,92,95,26,9,28,46,110,1,112,44,27, +9,26,183,140,1,27,48,48,52,52,49,47,28,139,184,25,9,26,44,112,110,44,28,9,26,93,93,1,194,22,38,38,40,41,38,38,21,69,69,69,74,48,51,28,29,27,27,4,254,217,7,5,27,28,28,28,50,87,121,81,84,20,22,46,44,100,57,64,5,7,46,42,42,46,1,46,5,7,49,50,28,28,29,174, +51,48,8,4,26,28,29,73,68,69,21,37,38,42,42,37,38,21,70,2,166,15,30,17,16,28,17,17,28,16,17,30,15,176,43,46,83,69,70,69,3,3,46,73,77,77,73,46,3,3,34,35,70,69,83,46,136,32,33,31,32,31,32,34,59,24,23,23,21,21,23,23,24,45,48,46,45,25,23,23,21,21,23,23,25, +45,46,48,217,73,77,43,46,82,69,70,36,36,4,4,8,2,145,156,156,145,2,49,1,2,46,16,22,37,50,83,95,96,81,50,37,22,16,45,4,49,143,79,81,81,79,143,50,5,45,16,22,36,51,81,96,95,82,51,38,21,16,46,2,1,62,131,71,73,73,71,131,26,34,34,13,21,23,15,16,17,16,55,52, +52,55,16,17,16,15,23,35,46,4,4,36,36,70,69,82,47,43,76,127,31,34,32,31,32,31,33,174,55,53,20,24,14,17,16,47,24,20,53,55,17,16,17,37,34,27,128,73,74,74,73,128,27,0,0,7,0,42,255,254,4,167,5,26,0,11,0,20,0,29,0,41,0,112,0,126,0,140,0,0,1,20,23,54,55,38, +39,54,55,38,39,6,5,52,38,21,6,21,22,23,54,37,6,23,54,55,46,1,39,6,5,52,39,6,7,22,23,6,7,22,23,54,3,38,7,6,7,38,39,54,55,22,23,54,55,38,53,52,63,1,21,22,21,20,7,30,1,23,54,55,22,23,6,7,38,39,38,7,22,23,22,20,7,6,7,22,23,6,35,38,39,6,7,6,7,35,38,39,53, +38,39,6,7,34,39,54,55,38,39,38,52,55,54,6,20,30,1,51,50,62,1,52,46,1,35,34,6,55,50,30,1,20,14,1,35,34,46,1,52,62,1,2,154,34,48,39,45,8,3,44,32,41,42,255,0,35,39,7,48,19,1,163,6,20,53,3,3,37,1,34,255,0,42,37,37,44,3,12,41,44,44,34,232,71,26,28,78,89,2, +2,160,148,73,39,43,34,144,1,143,34,36,40,5,74,147,161,1,2,89,78,28,18,79,23,17,50,49,21,28,30,44,1,12,57,44,52,61,83,22,28,28,77,58,55,44,58,12,1,45,30,28,20,49,50,17,45,91,165,91,90,165,91,93,166,87,88,166,254,73,139,79,77,139,75,76,139,77,78,140,2, +50,142,147,13,31,89,123,149,92,25,13,98,179,67,87,1,68,74,103,65,66,99,112,55,76,94,66,77,1,76,48,148,98,11,27,92,149,117,93,33,13,147,1,64,82,37,75,2,2,108,104,2,6,104,22,15,79,43,119,213,1,1,213,119,43,79,11,23,3,104,6,2,104,108,2,2,75,36,80,27,30, +90,192,88,39,31,64,68,10,48,58,41,19,30,119,119,30,1,18,42,59,48,10,69,65,30,38,88,192,90,30,119,180,165,91,91,165,180,167,91,91,71,74,140,152,138,77,77,138,152,140,74,0,4,0,34,0,2,4,175,4,40,0,7,0,13,0,21,0,37,0,0,1,51,1,21,33,39,35,0,23,1,21,33,53, +0,7,50,21,2,35,34,3,54,19,50,30,1,21,20,14,1,35,34,46,1,53,52,62,1,2,111,5,2,58,251,129,6,6,2,53,16,254,40,3,183,254,54,14,55,37,18,16,39,18,36,14,26,15,14,27,14,14,26,15,15,26,4,40,251,225,6,6,4,7,110,252,170,12,6,3,72,138,48,254,76,1,186,42,253,231, +14,25,15,15,25,14,14,25,15,15,25,14,0,0,1,0,136,0,8,4,73,5,34,0,19,0,0,1,51,23,21,1,20,51,4,21,23,1,39,53,0,53,52,35,36,47,1,4,42,12,19,253,220,80,1,82,7,252,198,12,2,54,104,254,193,14,6,5,34,19,6,254,38,62,73,12,62,253,170,19,6,2,12,11,62,65,15,62,0, +0,1,0,243,0,0,3,223,5,216,0,5,0,0,1,33,19,3,33,3,1,174,1,117,188,188,254,139,187,5,216,254,137,251,159,4,97,0,0,0,0,1,0,222,0,0,3,243,4,193,0,19,0,0,1,22,21,20,7,3,33,3,38,53,52,55,54,39,35,53,33,23,7,22,3,43,200,7,193,254,123,192,8,200,104,6,95,1,129, +1,97,1,3,246,54,145,26,29,253,8,2,248,31,27,142,54,21,109,72,72,1,109,0,3,0,46,1,114,4,163,3,243,0,90,0,121,0,153,0,0,1,39,35,34,39,38,7,6,21,20,7,6,7,6,7,6,35,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,51,50,31,1,22,51,50,55,54,55,54,55,54,39,38,39, +38,39,38,47,1,38,39,38,39,38,53,52,55,54,55,54,55,54,50,22,23,22,23,22,21,20,7,6,7,6,7,6,23,22,31,1,33,50,23,22,23,33,23,37,22,51,50,55,54,55,54,55,54,53,52,39,38,39,38,39,38,35,34,7,6,7,6,7,6,21,20,23,30,1,19,38,35,34,7,6,7,6,7,6,21,20,23,22,23,22,23, +22,51,50,55,54,55,54,55,54,53,52,39,38,39,38,2,203,151,80,122,20,30,2,1,7,9,18,16,25,20,30,25,26,25,18,15,16,13,9,9,17,17,25,20,30,24,26,44,68,64,26,9,16,13,13,2,2,3,2,9,8,16,55,59,43,26,18,20,10,14,9,9,18,19,22,25,50,51,18,22,9,13,9,6,9,12,2,4,24,29, +77,57,1,22,163,56,71,12,254,41,149,253,58,14,14,17,12,14,9,12,3,4,9,7,10,13,13,17,12,14,14,15,9,9,5,4,9,7,21,214,13,16,20,8,15,9,12,3,4,9,7,10,11,15,15,14,17,11,15,9,11,3,5,10,7,10,8,1,114,145,4,6,10,5,17,12,16,23,17,15,9,8,10,10,18,14,26,20,27,26,20, +23,16,16,9,8,10,18,27,2,3,9,11,5,5,17,16,13,14,13,48,24,17,11,17,19,21,26,21,26,20,23,17,17,7,8,21,17,21,20,25,23,24,21,17,8,12,5,9,15,19,76,58,22,29,53,146,85,6,4,5,7,9,12,12,12,9,17,12,9,12,5,6,4,5,7,9,12,12,12,10,16,12,20,1,231,7,4,5,7,11,10,12,12, +11,15,12,10,9,7,6,3,5,8,10,10,12,13,10,15,13,10,7,0,0,0,3,0,46,1,92,4,163,4,11,0,25,0,114,0,140,0,0,18,50,54,55,54,55,54,53,52,39,38,39,46,1,34,6,7,6,7,6,21,20,23,22,23,22,1,5,6,35,34,39,37,7,14,1,21,20,23,22,21,20,7,6,7,6,7,6,34,39,38,39,38,39,38,53, +52,55,54,55,54,55,54,59,1,50,55,62,1,55,54,52,39,46,1,39,38,43,1,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,50,23,22,23,22,23,22,21,20,7,6,21,20,22,31,1,37,54,51,50,23,36,34,6,7,6,7,6,21,20,23,22,23,30,1,50,54,55,54,55,54,53,52,39,38,39,38,172,35,28, +12,13,6,6,6,6,13,12,28,35,28,12,13,6,6,6,6,13,12,2,64,1,210,33,82,60,165,254,237,79,113,60,8,5,11,10,21,17,30,24,59,25,25,21,20,12,10,10,11,21,16,30,25,29,51,64,77,20,28,9,9,9,9,28,20,74,67,51,29,25,30,16,21,11,10,10,12,20,21,25,25,59,24,30,17,21,10, +11,5,8,60,113,79,1,19,165,60,82,33,252,45,35,28,12,13,6,6,6,6,13,12,28,35,28,12,13,6,6,6,6,13,12,1,152,10,10,11,11,12,14,14,12,11,11,9,11,11,9,11,11,12,14,14,12,11,11,10,1,18,190,47,65,110,33,47,10,10,6,17,12,19,26,23,22,19,16,12,10,10,10,18,15,26,23, +26,26,23,22,19,16,12,10,25,7,20,14,16,12,15,15,19,7,25,10,12,16,19,22,23,26,26,23,26,16,17,10,10,10,12,15,20,22,23,26,19,12,16,6,11,11,46,33,109,66,48,95,11,9,11,11,12,14,14,12,11,10,10,11,11,10,10,11,12,14,14,12,11,11,9,0,0,3,0,58,1,63,4,151,3,178,0, +89,0,120,0,151,0,0,1,51,7,33,6,7,6,35,33,7,6,7,6,21,20,23,22,23,22,21,20,7,6,7,14,1,34,39,38,39,38,39,38,53,52,55,54,55,54,63,1,54,55,54,55,54,55,54,39,38,39,38,39,38,35,34,15,1,6,35,34,39,38,39,38,39,38,53,52,55,62,1,55,54,51,50,23,22,23,22,23,22,21, +20,23,22,55,54,59,1,37,6,7,6,7,6,21,20,23,22,23,22,23,22,51,50,54,55,54,55,54,53,52,39,38,39,38,39,38,35,34,19,54,55,54,55,54,53,52,39,38,39,38,39,38,35,34,6,7,6,7,6,21,20,23,22,23,22,23,22,51,50,2,201,147,147,1,205,12,69,55,159,254,241,57,69,34,20,14, +9,6,8,12,9,21,18,50,49,24,22,19,19,7,8,13,8,21,18,25,43,57,54,15,8,9,2,3,2,2,13,7,21,5,30,62,66,43,25,24,30,19,25,16,17,9,8,12,13,35,25,25,25,29,19,25,16,17,9,6,2,4,27,17,122,79,254,111,15,10,6,11,9,4,5,9,7,16,12,16,14,29,10,11,7,8,4,4,10,5,19,11,16, +14,180,15,10,6,11,9,4,5,9,10,13,12,15,15,29,10,10,7,9,4,5,9,11,13,13,14,10,3,178,142,52,28,22,57,68,24,14,11,3,13,8,16,23,24,18,27,19,20,17,20,7,7,17,18,21,23,21,18,29,19,20,17,10,17,23,47,13,13,14,15,16,6,5,10,5,7,2,27,17,10,8,9,15,16,22,22,23,24,23, +22,34,10,10,8,9,15,16,22,16,12,19,3,10,7,4,58,6,9,6,16,14,11,14,10,12,8,6,6,4,12,10,9,12,15,13,11,10,12,8,7,5,4,254,24,6,9,5,17,13,11,15,10,11,9,8,4,3,12,9,10,12,13,12,15,9,11,9,9,3,4,0,0,0,0,9,0,61,1,74,4,148,4,3,0,90,0,120,0,150,0,180,0,210,0,254,1, +45,1,52,1,72,0,0,1,54,55,38,39,38,39,38,43,1,34,39,38,39,38,39,38,52,55,54,55,54,55,54,51,50,23,22,23,22,23,22,21,20,7,22,31,1,55,54,51,50,23,22,21,20,7,13,1,22,21,20,7,6,35,34,47,1,7,6,7,22,21,20,7,6,7,6,7,6,35,34,39,38,39,38,39,38,53,52,55,54,55,54, +55,54,59,1,50,55,54,6,50,55,54,55,54,55,54,53,52,39,38,39,38,39,38,34,7,6,7,6,7,6,21,20,23,22,23,22,23,18,50,55,54,55,54,55,54,53,52,39,38,39,38,39,38,34,7,6,7,6,7,6,21,20,23,22,23,22,23,18,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,50,23,22,23,22, +23,22,21,20,7,6,7,6,7,2,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,50,23,22,23,22,23,22,21,20,7,6,7,6,7,5,39,38,39,38,39,38,53,52,55,54,53,52,39,38,39,38,39,38,34,7,6,7,6,7,6,21,20,23,22,23,22,23,22,59,1,50,23,22,23,22,23,55,54,7,45,1,38,35,34,15,1, +6,7,6,7,6,7,6,43,1,34,7,6,7,6,7,6,21,20,23,22,23,22,23,22,50,55,54,55,54,55,54,53,52,39,38,53,52,55,54,37,23,22,51,50,55,37,38,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,50,23,22,23,1,157,8,5,5,8,6,17,56,63,46,31,31,25,28,23,13,13,13,11,27,19,32,29,33, +32,30,29,24,27,9,13,5,33,97,61,240,155,63,94,39,6,21,254,161,1,95,21,6,41,92,63,155,240,61,97,33,5,13,13,23,25,28,33,29,35,27,28,23,29,9,13,13,11,25,19,34,29,33,46,56,63,16,191,20,7,8,7,6,3,2,2,3,6,7,8,7,20,7,8,7,7,2,2,2,2,7,7,8,7,20,7,8,7,6,3,2,2,3, +6,7,8,7,20,7,8,7,7,2,2,2,2,7,7,8,34,34,15,14,12,13,6,6,6,6,13,12,14,15,34,15,14,12,13,6,6,6,6,13,12,14,15,34,15,14,12,13,6,6,6,6,13,12,14,15,34,15,14,12,13,6,6,6,6,13,12,14,1,12,26,102,27,15,8,11,8,4,9,9,18,14,26,22,50,22,22,18,17,10,9,9,9,18,14,26,22, +25,46,63,69,21,12,16,5,24,19,130,1,83,1,161,29,64,54,149,252,102,12,12,16,14,19,71,61,46,25,22,26,14,18,9,9,9,10,17,18,22,22,50,22,26,14,18,9,9,4,8,11,9,1,21,197,149,54,64,29,254,136,149,3,5,6,6,15,6,6,5,3,3,5,6,6,15,6,6,5,2,152,6,8,10,5,4,7,22,11,9, +23,19,29,26,66,26,23,27,18,12,11,11,11,21,25,23,32,27,20,13,6,41,25,95,62,57,9,12,21,8,143,142,8,26,8,8,57,62,95,25,41,7,16,16,32,27,29,20,22,9,11,11,11,19,24,25,37,23,31,28,24,24,19,13,11,22,6,207,2,4,5,5,5,3,5,5,3,5,5,5,3,3,3,3,6,4,5,3,5,5,4,4,5,5, +4,1,137,3,3,6,4,5,3,5,5,4,4,5,5,4,2,2,4,5,5,5,3,5,5,3,5,5,5,3,254,73,5,5,10,11,12,12,15,15,12,12,11,9,6,5,5,6,9,11,12,12,15,15,12,12,11,10,5,1,134,5,6,9,11,12,12,15,15,12,12,11,10,5,5,5,5,10,11,12,12,15,15,12,12,11,9,6,63,10,42,5,3,4,5,10,7,16,10,16, +22,20,18,17,13,12,8,8,10,15,13,22,20,22,22,20,18,17,13,11,9,23,7,9,12,6,17,12,186,133,170,32,59,100,46,21,20,11,9,7,24,8,11,13,17,19,19,22,23,19,22,13,15,10,8,8,11,13,18,18,19,23,16,9,17,7,14,1,1,63,80,60,33,154,30,15,6,7,4,3,3,4,7,6,15,6,6,4,4,4,4,6, +0,3,0,52,0,71,4,157,4,180,0,110,0,128,0,146,0,0,1,6,7,6,21,20,23,22,23,22,23,22,51,50,55,54,55,54,55,54,53,52,39,38,39,38,39,38,35,34,7,6,7,6,7,6,21,20,23,22,23,21,38,39,38,53,52,55,54,55,54,55,54,51,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,46, +2,53,52,55,54,55,38,53,52,55,18,51,50,23,22,21,20,7,6,35,34,7,6,7,6,21,20,23,22,21,20,7,6,7,6,35,34,23,54,55,54,55,54,55,22,23,22,7,6,7,6,7,6,39,38,1,22,23,22,21,20,7,6,7,6,35,34,39,54,55,54,53,52,1,122,3,1,7,7,8,14,15,17,81,107,100,89,87,71,74,35,35, +35,34,75,69,89,88,101,97,91,87,71,74,35,35,35,21,32,78,42,41,41,39,85,79,103,103,113,113,104,98,84,81,43,41,41,39,85,81,101,103,114,115,101,30,50,26,13,10,20,2,78,133,123,59,5,11,26,25,6,40,31,22,50,46,12,13,16,25,39,28,13,12,55,17,30,36,18,17,2,33,5, +13,2,7,14,20,25,27,15,20,1,47,45,16,12,15,10,22,7,21,7,42,12,21,22,1,64,4,5,17,20,21,17,19,13,14,8,37,37,36,72,73,86,87,99,103,87,83,77,70,38,37,37,36,72,73,87,87,103,98,88,49,46,111,80,98,101,113,115,103,96,87,80,44,43,43,41,83,81,102,100,118,111,103, +95,87,82,42,43,43,13,48,63,35,34,32,24,23,12,11,150,174,1,36,6,14,41,42,50,47,31,22,91,84,71,23,16,20,22,6,33,51,30,20,40,9,24,31,45,41,18,28,6,15,11,35,24,37,21,23,3,5,3,3,16,12,9,36,33,39,26,28,8,7,13,40,42,48,38,0,0,0,6,0,37,0,63,4,172,4,201,0,15, +0,28,0,44,0,74,0,105,0,137,0,0,1,38,39,38,39,55,6,21,20,23,22,23,22,23,22,23,19,38,39,38,34,7,6,7,19,54,51,50,23,19,23,6,7,6,7,37,54,55,54,55,54,55,54,53,52,38,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,34,39,38,39,38,39,38,53,52,55,54,55,54,55,19,34,7,6, +7,6,7,6,21,20,23,22,23,30,1,51,50,55,54,55,54,55,54,53,52,39,38,39,38,39,38,39,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,1,36,48,24,5,3,223,6,14,15,26,25,36,15,6,182,26,34,32,78,33,33,28,53,38,41,42,38,102, +224,2,7,24,48,254,238,10,11,36,24,27,15,14,211,47,19,21,16,16,9,8,8,9,16,16,21,19,47,19,20,17,17,8,8,8,8,17,17,20,42,100,93,89,74,75,36,37,37,37,74,72,182,102,102,92,89,74,75,36,36,36,35,76,71,92,90,104,116,106,101,86,84,44,43,43,40,88,82,105,105,117, +115,107,100,86,84,44,42,42,40,88,81,105,106,1,110,55,60,11,12,189,22,26,37,34,35,27,24,16,7,1,1,59,25,15,15,15,15,25,1,34,7,7,254,136,189,6,17,60,55,98,4,4,16,24,27,35,34,37,25,88,8,9,15,18,19,21,23,22,21,19,17,16,9,8,8,9,16,17,19,21,22,23,21,19,18,15, +9,1,144,38,37,74,75,89,89,106,100,91,89,74,73,77,38,37,75,74,89,89,102,106,89,85,79,72,39,38,75,44,42,86,83,104,103,121,114,106,98,89,84,43,45,45,42,85,83,104,103,117,118,106,98,89,83,45,44,0,0,0,1,0,61,0,60,4,148,4,91,0,45,0,0,19,53,55,39,51,23,54,55, +38,3,51,23,51,21,35,23,51,21,35,23,51,50,23,22,20,7,6,43,1,7,51,21,35,7,51,21,35,7,35,18,55,38,39,7,35,55,82,27,48,75,110,109,215,40,128,92,86,111,64,75,115,70,114,198,53,36,24,24,36,53,198,114,70,115,75,64,111,86,92,128,40,215,109,110,75,48,2,61,30, +3,164,151,10,7,208,1,15,113,60,97,60,149,19,13,33,13,19,149,60,97,60,113,1,8,215,8,9,150,163,0,0,0,0,5,0,63,0,115,4,146,3,150,0,13,0,20,0,34,0,41,0,45,0,0,1,37,33,5,54,55,54,55,54,50,23,22,23,22,23,5,17,5,22,21,20,13,1,33,37,6,7,6,7,6,34,39,38,39,38, +39,37,17,37,38,53,52,1,17,33,17,2,223,1,79,252,117,1,79,5,6,22,28,26,63,26,33,17,6,36,1,71,254,185,2,254,243,254,176,3,139,254,176,5,5,22,28,26,63,26,28,22,5,38,254,186,1,70,2,254,111,4,83,2,100,229,229,7,6,21,13,11,11,15,19,7,129,221,1,241,221,13,14, +15,81,229,229,6,6,21,12,11,11,12,21,6,129,221,254,15,220,14,15,14,254,96,3,35,252,221,0,0,4,1,68,0,11,3,141,4,234,0,75,0,198,0,217,0,233,0,0,1,52,55,54,63,1,54,55,50,59,1,38,39,38,39,38,53,52,55,54,51,50,23,22,23,22,31,1,22,23,54,55,54,55,54,55,54,53, +52,39,38,55,54,51,50,23,22,23,22,15,1,6,31,1,22,21,20,7,23,20,7,6,21,20,23,33,53,52,39,38,39,38,55,54,39,38,1,38,35,34,15,1,6,15,1,6,15,1,39,38,47,1,38,39,38,39,38,35,34,7,6,21,20,23,22,31,2,22,23,22,21,20,7,6,35,34,39,38,39,38,47,1,38,39,38,35,34,7, +6,7,22,23,22,23,22,23,22,21,20,7,6,7,21,20,23,22,23,22,23,22,21,20,7,38,39,38,39,38,63,1,54,39,38,39,6,35,34,39,38,39,38,35,34,23,22,23,22,31,1,22,21,7,33,39,52,55,54,47,1,54,53,52,39,38,55,19,54,39,1,7,22,23,22,23,22,23,22,51,50,55,54,53,52,39,38,39, +38,7,6,7,22,23,22,51,50,55,54,53,52,39,38,47,1,1,68,31,18,14,43,17,31,2,2,3,21,34,25,16,28,19,22,30,13,14,40,14,60,62,31,12,12,15,5,4,9,4,10,4,1,5,30,22,33,45,24,11,1,9,2,7,1,2,2,3,1,3,17,3,1,254,64,4,7,31,40,1,2,24,15,2,19,3,32,28,4,4,1,8,29,4,18,44, +20,8,35,14,37,62,22,16,14,11,14,7,6,24,11,15,78,112,78,77,3,16,4,4,18,15,4,3,38,95,42,6,35,24,16,10,5,4,3,7,40,33,10,7,38,41,17,12,1,44,19,20,44,8,2,23,102,38,5,6,11,1,6,2,6,6,12,23,33,11,13,19,14,40,8,3,2,8,6,3,8,75,1,1,1,95,1,10,11,1,1,2,7,5,1,9,1, +2,254,90,14,29,48,45,14,3,1,14,8,9,3,2,10,4,5,89,105,12,2,68,31,12,9,13,7,3,10,6,9,99,2,112,45,41,5,26,76,30,9,38,103,75,29,49,30,22,23,26,4,10,21,91,154,78,30,17,14,51,36,26,13,110,47,5,9,9,34,33,24,48,21,15,123,73,246,23,34,18,29,72,30,35,102,24,109, +15,116,50,62,149,15,27,44,55,72,31,66,73,46,2,59,47,56,91,24,44,160,23,5,13,9,11,81,31,91,122,41,12,10,9,5,9,25,46,22,41,209,83,57,76,10,7,15,3,1,16,5,6,42,69,31,3,25,18,8,6,9,18,32,26,15,9,39,43,40,29,52,37,26,2,40,52,23,13,32,14,5,4,13,7,42,88,13,8, +19,18,62,12,9,9,4,21,3,4,10,55,3,28,65,41,18,175,8,9,130,150,48,39,45,53,55,48,43,73,59,45,37,1,10,14,42,254,167,17,35,37,40,48,10,10,14,13,7,8,17,19,7,4,93,15,16,39,53,46,7,14,9,8,15,14,9,4,85,0,0,8,0,45,0,149,4,164,3,252,0,6,0,57,0,76,0,112,0,123,0, +127,0,137,0,141,0,0,19,22,55,54,53,52,39,5,34,39,38,35,34,7,6,43,1,34,39,15,1,55,38,53,52,63,1,54,55,54,55,54,55,54,51,50,23,55,54,51,50,23,22,21,7,23,22,51,50,55,51,22,21,20,7,35,53,6,37,54,55,54,55,19,39,38,35,34,7,6,15,1,22,21,20,7,54,37,34,47,1,7, +20,7,54,55,22,21,20,7,6,35,34,7,22,21,20,7,50,55,54,51,50,23,22,51,50,55,54,53,52,39,6,55,22,21,20,7,21,51,54,53,52,39,5,54,55,15,1,6,21,20,23,22,23,54,53,52,15,1,55,38,169,19,15,11,12,2,116,33,77,35,20,27,108,53,23,71,59,26,64,188,92,5,10,50,20,18,66, +88,45,48,25,25,37,45,109,32,42,27,21,9,135,145,32,28,39,4,161,63,44,177,78,253,171,24,21,6,3,239,26,12,22,63,168,39,24,14,33,31,28,2,159,38,17,173,82,59,45,62,11,26,60,92,45,17,24,14,82,53,45,54,28,69,33,34,36,98,31,36,18,54,36,33,113,34,44,253,162,59, +10,116,64,80,34,22,31,16,251,35,67,5,1,127,2,28,22,22,22,12,223,10,3,11,6,42,70,83,192,13,23,18,34,165,68,24,88,64,33,19,9,37,122,36,40,18,21,156,96,21,21,93,129,148,106,77,26,166,26,80,20,11,1,10,21,10,166,38,79,47,43,28,64,25,6,252,12,112,95,117,60, +2,30,10,15,13,11,28,1,28,51,30,32,9,8,9,4,26,68,77,75,90,5,21,82,100,89,76,54,68,149,95,89,171,66,73,139,53,19,46,33,22,14,2,33,39,39,107,71,28,26,0,0,0,0,7,0,87,0,132,4,122,4,166,0,21,0,27,0,34,0,41,0,51,0,83,0,90,0,0,1,54,55,54,53,52,47,1,6,35,20,7, +6,35,20,7,23,22,51,50,55,54,1,63,1,15,2,19,55,1,19,37,1,55,5,1,22,53,52,39,1,0,54,53,52,39,1,7,1,22,51,1,54,55,54,55,54,51,50,23,22,21,20,7,6,7,6,7,6,7,6,7,6,35,34,39,38,53,52,55,54,55,54,23,7,1,22,51,50,39,3,242,7,4,5,1,48,19,24,44,44,59,18,192,7,6, +8,12,9,253,40,124,11,119,124,11,107,215,2,6,149,253,228,253,251,14,1,105,1,171,53,2,254,46,1,85,44,5,254,92,92,1,164,14,12,253,234,10,13,12,13,11,8,11,8,6,4,5,7,8,12,11,12,12,13,12,7,11,8,5,3,4,8,8,37,103,1,210,9,8,46,1,1,11,6,10,13,8,4,7,193,18,59,44, +45,22,20,48,1,5,4,2,106,123,119,11,123,119,1,51,15,253,251,253,228,150,2,4,216,17,254,86,1,46,8,10,1,210,253,84,44,27,12,14,1,165,92,254,91,5,2,94,11,9,8,4,3,6,7,11,8,11,13,12,14,10,12,8,8,4,3,6,5,13,9,11,13,11,13,198,11,254,45,1,53,0,0,0,0,7,0,38,0, +224,4,171,2,196,0,19,0,25,0,32,0,39,0,45,0,69,0,76,0,0,0,52,39,38,39,38,47,1,20,7,22,20,7,22,21,55,54,55,54,55,5,53,39,7,21,23,3,55,33,13,1,33,39,55,33,54,53,52,39,33,4,52,39,33,21,33,36,52,55,54,55,62,1,50,22,23,22,23,22,20,7,6,7,14,1,34,38,39,38,39, +23,7,33,54,53,52,39,4,3,3,2,5,3,8,149,15,36,36,15,149,8,3,5,2,252,230,67,67,67,124,124,2,93,1,170,254,86,253,163,124,234,1,236,18,25,253,226,2,86,35,254,27,1,229,253,117,3,2,5,5,13,14,13,5,6,2,3,3,2,6,5,13,14,13,5,5,2,142,57,2,30,25,18,1,202,17,8,7,6, +5,4,90,23,15,40,102,40,14,23,89,4,5,7,7,60,153,80,80,153,80,1,0,142,242,241,142,213,18,16,19,18,225,80,17,114,43,28,13,12,11,10,11,11,10,11,12,13,28,13,12,10,10,12,12,10,10,12,86,72,18,20,16,18,0,0,0,0,7,0,87,0,187,4,122,4,221,0,21,0,27,0,34,0,41,0,51, +0,83,0,90,0,0,1,38,39,38,35,34,15,1,22,21,50,23,22,21,50,23,55,54,53,52,39,38,1,39,31,2,39,7,47,1,1,37,3,1,39,23,1,54,53,52,7,46,1,35,34,7,1,23,1,54,53,1,38,39,38,39,38,53,52,55,54,51,50,23,22,23,22,23,22,23,22,23,22,21,20,7,6,35,34,39,38,39,38,55,1, +54,35,34,7,1,3,242,7,9,12,8,6,7,192,18,59,44,44,24,19,48,1,5,4,253,26,119,11,124,119,11,136,161,14,2,5,2,28,149,253,250,15,12,1,210,2,53,30,44,27,12,14,254,92,92,1,164,5,253,163,12,8,8,4,3,5,8,11,7,12,13,12,12,11,12,8,7,5,4,6,8,11,8,11,13,12,13,15,1, +169,1,46,8,9,254,46,4,86,7,5,4,1,48,20,22,45,44,58,19,193,7,4,8,13,10,253,163,11,119,123,11,119,173,160,216,2,5,149,253,229,253,250,192,104,1,211,10,8,46,1,111,44,5,254,91,92,1,165,14,12,253,232,12,13,11,13,11,9,13,5,6,3,4,8,8,12,10,14,12,13,11,8,11, +7,6,3,4,8,9,220,1,170,54,2,254,46,0,0,0,0,2,0,59,1,43,4,150,3,93,0,35,0,67,0,0,18,52,39,22,37,5,21,37,46,1,39,38,34,7,6,7,6,7,6,20,23,22,23,22,23,22,50,55,62,1,55,37,21,5,36,7,54,20,7,54,5,37,5,6,7,6,34,39,38,39,38,39,38,52,55,54,55,54,55,54,50,23,22, +23,5,37,4,39,98,38,224,1,162,1,215,254,73,4,11,13,10,23,10,11,8,8,4,5,5,6,6,8,11,10,23,10,13,11,4,1,183,254,41,254,94,224,116,17,131,1,156,1,78,254,241,17,20,20,47,20,21,16,17,9,8,8,9,17,16,21,20,47,20,20,17,1,15,254,178,254,100,131,1,201,247,73,3,87, +210,63,21,6,12,7,4,4,5,8,6,13,10,24,10,14,5,8,4,5,5,6,12,6,22,64,209,86,2,249,105,68,2,86,141,18,16,9,9,9,9,16,17,20,21,47,20,20,18,16,9,8,8,9,16,19,141,86,3,0,0,1,0,37,1,17,4,172,3,27,0,38,0,0,1,37,21,5,36,7,54,52,39,22,37,5,21,37,38,39,38,39,38,34, +7,6,7,6,7,6,21,20,23,22,23,22,23,22,50,55,54,55,54,2,232,1,196,254,4,254,64,203,41,41,203,1,192,1,252,254,60,5,13,11,15,14,34,14,15,11,13,5,7,7,5,13,11,15,14,34,14,15,11,13,1,247,23,27,226,93,2,78,184,79,3,93,226,27,24,14,12,12,6,7,7,6,12,12,14,15,17, +16,15,14,12,12,6,7,7,6,12,12,0,1,0,152,0,192,4,57,4,124,0,28,0,0,1,50,23,22,51,50,55,18,55,54,51,50,22,21,20,7,0,1,6,35,34,39,38,39,38,53,52,55,54,1,24,34,18,35,15,12,12,245,210,54,118,28,19,29,254,174,254,224,20,62,63,12,30,40,45,61,37,2,80,56,106,18, +1,138,243,63,10,8,13,35,254,106,254,60,32,6,13,121,134,34,36,34,22,0,0,0,0,1,0,74,0,114,4,135,4,66,0,29,0,0,1,50,23,22,51,50,55,18,55,54,51,50,23,22,21,20,7,0,7,6,35,34,39,38,39,38,53,52,55,54,1,7,34,18,34,15,12,12,246,209,89,84,111,22,10,20,253,205, +107,37,133,44,48,20,50,63,61,86,2,142,56,106,18,1,105,153,65,7,2,20,15,24,253,123,195,67,23,11,123,156,117,43,28,39,0,0,0,1,0,129,0,113,4,80,4,63,0,11,0,0,9,1,7,9,1,39,9,1,55,9,1,23,2,219,1,115,115,254,141,254,141,115,1,115,254,141,115,1,115,1,116,115, +2,88,254,140,114,1,115,254,141,114,1,116,1,115,115,254,141,1,115,114,0,0,0,1,0,64,0,188,4,81,4,207,0,11,0,0,9,1,7,9,1,39,9,1,55,9,1,23,3,53,1,28,237,254,228,254,229,237,1,28,254,228,237,1,27,1,28,237,2,197,254,229,237,1,27,254,229,237,1,27,1,27,237,254, +229,1,28,237,0,0,0,1,0,131,255,236,4,78,4,190,0,66,0,0,1,50,23,22,23,54,51,50,23,22,21,20,7,6,7,22,23,22,21,20,15,1,22,21,20,7,6,35,34,39,38,39,6,3,6,35,34,39,38,53,52,55,54,55,18,55,38,39,38,53,52,55,54,51,50,23,54,55,54,51,50,23,22,23,54,55,54,3,201, +8,13,14,14,24,14,12,21,13,18,169,159,66,116,10,25,26,3,17,22,9,21,17,97,104,140,180,26,62,29,4,41,9,4,22,166,185,99,33,7,15,15,13,12,19,7,11,14,23,26,8,44,72,115,166,19,4,190,13,13,22,42,22,14,17,22,19,183,220,161,194,17,9,19,20,18,10,16,25,13,14,21, +125,169,182,254,208,44,34,23,50,65,25,11,34,1,3,216,236,127,28,9,11,21,21,23,14,9,13,24,137,123,149,166,20,0,0,0,1,0,51,255,253,4,158,5,43,0,81,0,0,1,50,23,22,23,54,23,22,23,22,21,20,7,6,3,22,23,22,21,20,7,6,7,6,7,6,35,34,39,6,7,6,35,34,39,38,39,6,7, +6,35,6,39,38,39,6,35,34,39,38,53,52,55,38,39,38,53,52,55,54,55,38,39,38,53,52,55,54,51,50,23,54,55,54,51,50,23,22,23,54,55,54,4,0,26,23,18,7,22,9,28,13,12,14,211,206,130,129,15,26,18,32,2,12,21,28,32,26,7,12,31,24,20,23,78,106,201,77,15,18,17,16,13,2, +17,16,22,25,32,27,8,8,16,21,114,172,107,87,19,20,14,19,23,42,1,10,20,14,38,12,92,132,202,218,10,5,42,26,19,51,1,5,10,12,12,18,35,14,192,254,239,179,142,15,22,42,23,15,2,15,30,51,21,16,9,24,24,84,167,229,118,22,2,33,27,12,11,26,31,15,23,40,2,12,21,21, +18,27,154,186,165,234,53,25,22,43,28,34,12,22,44,23,171,163,231,191,10,0,0,0,0,3,0,64,0,5,4,145,4,86,0,11,0,23,0,35,0,0,1,17,33,17,33,17,33,17,33,17,33,17,37,33,17,33,17,33,17,33,17,33,17,33,3,33,21,33,17,35,17,33,53,33,17,51,3,11,254,187,254,197,1,59, +1,69,1,59,255,0,1,74,254,182,254,69,254,182,1,74,1,187,148,1,74,254,182,147,254,182,1,74,147,2,208,1,60,254,196,254,187,254,197,1,59,1,69,59,254,69,254,182,1,74,1,187,1,75,254,33,148,254,183,1,73,148,1,75,0,0,0,1,0,86,0,7,4,123,4,6,0,11,0,0,1,33,17,33, +17,33,17,33,17,33,17,33,2,247,1,132,254,124,254,227,254,124,1,132,1,29,2,143,254,238,254,139,1,117,1,18,1,118,0,2,0,57,0,6,4,152,4,102,0,11,0,15,0,0,1,33,21,33,17,35,17,33,53,33,17,51,3,51,53,35,2,194,1,214,254,42,180,254,43,1,213,180,179,178,178,2,144, +180,254,42,1,214,180,1,214,253,119,178,0,2,0,48,0,0,4,161,4,114,0,3,0,15,0,0,1,33,17,33,37,33,17,33,17,33,17,33,17,33,17,33,1,209,1,47,254,209,1,48,1,160,254,96,254,207,254,96,1,160,1,49,1,161,1,47,1,254,207,254,96,1,160,1,49,1,160,0,0,1,0,155,0,3,4, +41,5,30,0,11,0,0,1,33,21,33,17,35,17,33,53,33,17,51,2,203,1,94,254,162,210,254,162,1,94,210,3,192,210,253,22,2,234,210,1,94,0,2,0,126,0,1,4,83,5,28,0,15,0,27,0,0,1,51,23,17,33,17,33,39,17,35,39,17,33,17,33,23,7,17,35,17,33,21,33,17,51,17,33,53,3,76,131, +131,254,250,254,188,131,131,132,1,7,1,68,131,175,193,254,250,1,6,193,1,7,4,21,131,254,188,253,179,131,1,202,131,1,68,1,7,132,218,1,6,254,250,193,253,179,2,77,193,0,3,0,144,0,4,4,65,4,194,0,11,0,23,0,35,0,0,1,53,33,21,35,17,51,17,33,17,51,17,39,51,17, +35,17,33,17,35,17,51,53,33,3,51,21,35,17,35,17,35,53,51,53,51,3,6,254,197,245,245,1,59,245,175,245,245,254,57,245,245,1,199,140,245,245,175,245,245,175,3,157,227,227,254,203,253,221,2,35,1,53,65,254,73,253,221,2,35,1,183,228,254,154,179,253,221,2,35, +179,228,0,0,0,1,0,48,0,3,4,161,4,118,0,81,0,0,1,35,34,7,6,7,6,7,6,21,35,17,51,20,23,22,23,22,23,22,59,1,53,52,39,38,39,38,39,38,35,53,33,21,34,7,6,7,14,1,29,1,51,50,55,54,55,54,55,54,53,51,17,35,52,39,38,39,38,39,38,43,1,21,20,23,22,23,22,23,22,51,21, +33,53,50,55,54,55,62,1,53,2,47,93,76,69,68,55,51,33,28,38,38,28,31,53,52,71,66,79,93,28,30,54,51,72,62,83,3,107,83,62,72,51,56,56,93,79,66,71,52,53,31,28,38,38,28,33,51,53,70,69,76,93,28,30,54,51,72,62,83,252,149,83,62,72,51,56,56,2,4,29,28,56,50,73, +60,85,3,106,84,60,70,54,54,30,27,93,76,69,70,54,50,33,28,38,38,28,33,50,56,137,76,93,27,30,54,54,70,60,84,252,150,85,60,73,50,55,29,29,94,76,69,70,54,50,33,28,38,38,28,33,50,56,137,76,0,0,8,0,71,0,2,4,138,4,238,0,11,0,17,0,20,0,23,0,26,0,29,0,32,0,35, +0,0,1,19,33,3,19,33,11,1,33,19,3,33,23,7,23,33,55,47,1,7,51,31,1,55,3,7,51,5,35,23,47,1,7,19,55,35,2,104,182,1,108,182,182,254,148,182,182,254,149,182,182,1,107,48,135,135,1,13,135,135,135,87,175,141,88,88,88,88,176,254,195,175,87,228,88,88,88,88,176, +4,238,254,196,254,198,254,197,254,197,1,59,1,59,1,58,81,233,234,234,233,233,152,81,152,152,254,198,153,81,152,233,153,153,1,59,152,0,1,0,31,255,236,4,178,4,127,0,67,0,0,1,53,52,39,38,53,52,55,54,50,23,22,21,20,7,6,29,1,51,50,55,54,51,50,23,22,20,7,6, +35,34,39,38,43,1,21,20,23,22,21,20,7,6,34,39,38,53,52,55,54,61,1,35,34,7,6,35,34,39,38,52,55,54,51,50,23,22,51,2,67,58,33,41,42,91,42,41,33,58,24,141,92,53,89,76,36,36,36,36,76,89,53,92,141,24,58,33,41,42,91,42,41,33,58,24,141,92,53,89,76,36,36,36,36, +76,89,53,92,141,2,91,24,141,92,53,89,76,36,36,36,36,76,89,53,92,141,24,58,33,41,42,91,42,41,33,58,25,141,91,53,89,76,36,37,37,36,76,89,53,91,141,25,58,33,41,42,91,42,41,33,58,0,0,0,0,1,0,28,255,239,4,181,4,137,0,131,0,0,1,38,39,35,6,7,6,7,14,1,35,34, +38,39,38,39,38,52,55,54,55,62,1,51,50,22,23,22,23,22,23,51,54,55,54,55,53,38,39,38,39,46,1,53,52,54,55,54,55,54,50,23,22,23,30,1,21,20,6,7,6,7,6,7,21,22,23,22,23,51,54,55,54,55,62,1,51,50,22,23,22,23,22,20,7,6,7,14,1,35,34,38,39,38,39,38,39,35,6,7,6, +7,21,22,23,22,23,30,1,21,20,6,7,6,7,6,34,39,38,39,46,1,53,52,54,55,54,55,54,55,53,38,2,37,12,7,162,1,8,15,22,25,62,35,34,63,24,24,14,13,13,14,24,24,63,34,35,62,25,26,11,7,2,162,7,12,13,16,12,15,32,23,25,26,26,25,25,30,30,71,30,30,25,25,26,26,25,27,28, +18,9,16,13,12,7,162,2,7,11,26,25,62,35,34,63,24,24,14,13,13,14,24,24,63,34,35,62,25,22,15,8,1,162,7,12,13,16,9,18,28,27,25,26,26,25,25,30,30,71,30,30,25,25,26,26,25,23,32,15,12,16,1,249,13,16,12,16,32,22,26,25,25,26,24,30,31,70,30,31,24,25,26,26,25,26, +29,17,10,16,13,12,8,162,2,7,15,22,25,62,35,35,62,24,24,14,13,13,14,24,24,62,35,35,62,25,25,12,7,2,162,8,12,13,16,10,17,29,26,25,26,26,25,24,31,30,70,31,30,24,26,25,25,26,22,32,16,12,16,13,12,8,161,3,7,11,26,24,63,35,34,62,25,23,14,13,13,14,23,25,62,34, +35,63,24,22,15,8,2,161,8,0,1,0,26,255,237,4,183,4,138,0,155,0,0,1,52,39,38,39,38,39,38,39,46,1,53,52,55,54,55,54,55,54,51,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,7,6,7,6,21,50,55,54,55,54,55,54,55,54,55,54,51,50,23,22,23,22,23,22,20,7,6,7,6,7,6,35,34, +39,38,39,38,39,38,39,38,39,38,35,20,23,22,23,22,23,22,23,22,23,22,21,20,7,6,7,6,7,6,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,55,54,55,54,53,34,7,6,7,6,7,6,7,14,1,35,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,51,50,23,22,23,22,23,22,23,22,23,22, +2,66,15,18,28,10,12,19,7,31,30,15,17,29,24,44,35,44,43,37,41,27,29,17,15,15,17,29,7,20,6,15,32,14,15,51,33,44,25,10,9,14,8,30,38,38,42,45,35,39,29,28,18,16,16,18,28,29,39,35,45,42,38,38,30,8,14,9,10,31,38,36,48,15,20,26,9,13,19,7,30,16,15,15,17,29,27, +41,36,87,36,41,27,29,17,15,15,16,30,7,19,13,9,30,16,15,48,36,39,30,10,9,14,8,29,76,43,44,36,38,29,26,20,17,17,18,28,29,38,36,44,47,34,38,29,8,14,4,15,31,38,36,2,98,51,34,41,26,11,9,14,7,29,77,42,44,37,38,29,24,22,16,16,19,27,29,38,37,44,46,34,39,29,7, +14,4,16,30,37,37,48,15,21,25,10,12,19,8,29,16,16,16,16,29,28,41,36,87,35,41,28,29,17,15,15,16,30,8,19,12,10,30,16,15,52,33,44,25,10,9,14,7,30,38,38,43,44,36,39,29,27,18,16,16,18,27,29,39,36,44,43,38,38,30,7,14,9,10,31,38,36,49,15,16,30,11,12,18,8,30, +31,15,17,29,25,44,35,44,43,36,41,28,29,16,16,16,16,29,8,20,6,15,31,15,15,0,0,1,0,23,255,229,4,186,4,136,1,48,0,0,1,50,23,22,23,22,23,22,21,20,7,6,7,54,55,54,51,50,23,22,23,22,23,22,21,20,7,14,1,7,6,35,34,39,38,39,38,39,21,51,38,39,38,39,38,53,52,54,55, +54,55,54,51,50,23,22,23,22,23,22,21,20,7,6,7,54,55,54,51,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,39,22,23,22,21,20,6,7,6,7,6,35,34,39,38,39,38,39,38,53,52,55,54,55,54,55,35,21,54,55,54,55,54,51,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34, +39,38,39,22,23,22,21,20,7,6,7,6,7,6,34,39,38,39,38,39,38,53,52,55,54,55,6,7,6,35,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,51,50,22,23,22,23,53,35,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,39,38,39,38,53,52,55,54,55,6,7,6,35,34,39,38,39,38,39,38, +52,55,54,55,54,55,54,51,50,23,22,23,38,39,38,53,52,55,54,55,54,55,54,51,50,23,22,23,22,23,22,21,20,7,6,7,6,7,51,53,6,7,6,7,6,35,34,39,46,1,39,38,53,52,55,54,55,54,55,54,51,50,23,22,23,38,39,38,53,52,55,54,55,54,55,54,2,104,23,18,21,14,15,8,8,8,8,15,8, +15,19,22,23,18,20,15,15,8,8,8,8,31,19,19,22,23,18,19,15,11,8,226,13,11,15,8,9,17,15,15,20,19,22,22,19,20,15,15,8,9,9,6,7,15,20,19,21,25,17,19,16,14,9,8,8,9,14,17,18,20,22,21,19,20,15,7,6,9,17,15,13,22,19,22,19,22,20,15,15,8,9,9,8,15,11,13,225,7,11,13, +22,18,23,22,18,20,15,15,8,8,8,8,15,14,21,17,23,20,21,15,9,15,8,9,9,8,15,14,21,18,45,18,21,14,15,8,9,9,8,15,9,15,18,23,23,17,21,14,15,8,8,8,8,15,15,20,18,22,21,40,15,11,7,225,13,10,17,7,8,8,8,16,16,18,20,21,23,19,19,15,15,9,8,8,6,8,17,18,19,22,22,19,20, +15,14,9,8,8,9,14,13,22,19,22,22,19,20,15,8,6,8,8,9,15,14,20,19,23,21,20,19,15,16,8,8,8,9,15,10,13,225,8,11,15,19,18,23,22,18,20,31,7,9,9,7,16,14,21,17,23,23,18,15,9,16,8,8,8,8,16,14,20,18,4,135,8,9,14,15,20,19,23,21,19,20,15,7,6,8,8,9,14,15,20,19,22, +24,18,19,30,9,7,7,9,15,10,13,224,7,11,15,19,18,23,22,39,15,15,9,7,7,9,15,15,20,18,23,21,20,15,8,15,8,8,8,8,15,14,21,18,22,23,19,20,14,17,7,7,7,9,15,9,15,19,21,20,42,14,13,10,9,9,7,16,15,20,18,23,23,17,19,16,10,8,225,14,10,12,11,8,8,9,14,16,20,19,21,22, +19,20,16,14,9,8,8,6,7,14,20,19,22,22,20,19,15,15,9,8,8,9,15,15,19,20,22,22,19,20,14,7,6,8,8,9,14,16,20,19,22,21,19,20,16,14,9,8,17,14,10,14,224,7,10,18,17,18,23,22,19,20,14,17,7,8,8,8,16,14,20,18,23,22,19,15,9,17,7,7,7,9,15,14,20,18,46,18,20,15,13,10, +8,8,8,15,8,15,19,22,23,18,20,14,15,9,8,8,9,15,14,20,19,22,23,18,19,15,11,7,224,13,10,15,9,7,7,9,30,19,20,22,19,22,20,15,14,9,8,8,6,7,15,20,19,21,23,19,20,15,14,9,8,0,0,0,1,0,43,255,231,4,166,4,106,0,31,0,0,19,50,55,54,55,54,55,54,53,20,23,22,23,22,23, +22,51,34,7,6,7,6,7,6,21,52,39,38,39,38,39,38,43,115,105,100,85,83,43,42,43,39,87,80,105,104,116,116,104,105,80,87,39,43,42,43,83,85,100,105,2,41,44,41,85,82,104,101,120,117,104,98,88,82,44,44,44,44,82,89,97,105,116,119,102,103,83,85,41,44,0,2,0,37,255, +230,4,172,4,116,0,31,0,63,0,0,19,50,23,22,23,22,23,22,21,52,55,54,55,54,55,54,51,34,39,38,39,38,39,38,53,20,7,6,7,6,7,6,33,50,55,54,55,54,55,54,53,20,23,22,23,22,23,22,51,34,7,6,7,6,7,6,21,52,39,38,39,38,39,38,240,76,69,65,56,54,29,27,28,26,58,52,68, +68,77,77,68,68,52,58,26,28,27,29,54,56,65,69,254,234,116,106,100,86,84,44,42,43,40,88,81,106,104,118,118,104,106,81,88,40,43,42,44,84,86,100,106,2,45,28,28,55,54,68,67,79,77,69,64,58,54,29,28,29,29,54,58,63,70,76,79,67,67,54,55,28,29,45,42,85,83,104, +103,121,118,106,98,89,83,44,45,44,45,82,90,98,106,118,121,103,104,84,85,42,44,0,0,2,0,40,255,240,4,169,4,56,0,9,0,19,0,0,19,37,27,1,5,3,19,37,5,19,1,3,33,1,3,9,1,3,1,33,41,1,116,203,204,1,116,245,26,254,155,254,156,26,1,74,135,254,72,1,99,136,1,100,1, +101,136,1,99,254,72,2,149,93,1,70,254,186,93,254,217,254,130,143,143,1,126,2,202,254,93,254,253,254,94,1,3,254,253,1,162,1,3,0,0,2,0,67,255,230,4,142,4,53,0,9,0,41,0,0,1,3,33,5,3,37,5,3,37,33,3,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,39,38, +39,38,53,52,55,54,55,54,55,54,2,104,122,254,116,1,64,122,1,64,1,65,122,1,64,254,116,123,110,101,95,82,80,41,40,40,38,83,78,99,100,111,109,101,95,82,80,41,40,40,38,83,77,100,100,4,48,254,135,233,254,136,233,233,1,120,233,1,125,42,40,81,79,98,98,114,108, +101,93,84,80,41,42,42,40,81,79,98,98,111,111,101,93,84,78,43,42,0,0,0,0,2,0,40,255,230,4,169,4,46,0,29,0,39,0,0,0,34,7,6,7,6,7,6,21,20,23,22,23,22,23,22,50,55,54,55,54,55,54,53,52,39,38,39,38,39,3,19,33,1,19,9,1,19,1,33,2,152,95,41,40,34,34,17,17,17, +17,34,34,40,41,95,41,40,34,34,17,17,17,17,34,34,40,89,136,1,184,254,157,136,254,155,254,156,136,254,157,1,184,2,184,17,19,31,36,40,42,47,46,42,40,35,32,19,17,17,19,32,35,40,42,46,47,42,40,36,31,19,1,135,254,93,254,253,254,94,1,3,254,253,1,162,1,3,0,3, +0,35,255,233,4,174,4,60,0,9,0,39,0,49,0,0,19,37,27,1,5,3,19,37,5,19,0,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,34,39,38,39,38,39,38,53,52,55,54,55,54,55,19,3,33,1,3,9,1,3,1,33,35,1,120,205,206,1,120,248,26,254,152,254,153,26,1,29,97,41,40,35,34,17,17,17, +17,34,35,40,41,97,41,40,35,34,17,17,17,17,34,35,40,89,137,254,68,1,103,137,1,103,1,104,137,1,103,254,68,2,149,94,1,73,254,183,94,254,214,254,127,144,144,1,129,1,87,17,19,32,36,40,42,48,46,43,40,36,32,19,17,17,19,32,36,40,43,46,48,42,40,36,32,19,1,139, +254,89,254,251,254,90,1,5,254,251,1,166,1,5,0,0,0,3,0,40,255,240,4,169,4,56,0,9,0,19,0,29,0,0,1,23,51,7,23,39,7,55,39,51,19,3,33,5,3,37,5,3,37,33,3,19,33,1,19,9,1,19,1,33,2,104,69,219,177,67,178,177,67,177,219,68,101,254,181,1,12,103,1,11,1,12,103,1, +12,254,181,102,136,1,184,254,157,136,254,155,254,156,136,254,157,1,184,3,10,210,129,209,129,129,209,129,1,105,254,198,194,254,198,195,195,1,58,194,1,209,254,93,254,253,254,94,1,3,254,253,1,162,1,3,0,3,0,61,255,252,4,148,4,28,0,9,0,19,0,29,0,0,1,23,51, +7,23,39,7,55,39,51,27,1,33,5,19,37,5,19,37,33,55,7,33,23,7,55,23,39,55,33,2,104,27,84,68,26,69,68,26,68,84,26,131,1,168,254,170,131,254,168,254,169,131,254,170,1,168,130,78,255,0,207,80,207,208,80,207,255,0,2,73,81,50,80,49,49,80,50,2,35,254,109,249, +254,109,249,249,1,147,249,172,243,150,243,150,150,243,150,0,6,0,40,255,246,4,169,4,63,0,2,0,5,0,8,0,11,0,14,0,24,0,0,45,1,53,37,5,55,1,3,39,37,33,7,17,3,23,17,19,33,1,19,9,1,19,1,33,1,93,1,11,254,80,1,12,164,1,12,103,165,1,177,254,181,102,101,101,136, +1,184,254,157,136,254,155,254,156,136,254,157,1,184,114,194,173,140,194,54,254,145,1,57,54,140,140,1,198,254,198,140,2,93,254,94,254,253,254,94,1,3,254,253,1,162,1,3,0,0,0,2,0,46,0,17,4,163,4,5,0,13,0,23,0,0,1,5,19,47,1,5,39,19,37,33,19,23,19,33,37,3, +33,23,3,55,23,3,55,33,4,162,254,196,121,114,235,254,226,114,121,254,196,1,136,121,113,109,1,34,254,0,95,254,208,246,94,247,246,94,246,254,208,2,108,231,254,140,37,171,208,37,1,116,230,1,117,37,254,176,253,254,223,180,254,223,179,179,1,33,180,0,0,0,0, +1,0,54,255,254,4,155,4,130,0,17,0,0,1,17,51,17,37,23,13,1,7,37,17,35,17,5,39,45,1,55,1,237,247,1,58,124,254,198,1,58,124,254,198,247,254,198,124,1,57,254,199,124,3,23,1,107,254,148,182,214,181,182,214,181,254,149,1,107,181,214,182,181,214,0,0,2,0,87, +255,255,4,122,4,96,0,5,0,23,0,0,1,7,23,51,55,39,5,37,55,5,17,23,17,37,23,13,1,7,37,17,35,17,5,39,2,14,90,90,180,90,90,254,242,254,163,90,1,93,180,1,94,90,254,162,1,94,90,254,162,180,254,163,90,2,203,155,157,157,155,155,202,156,203,1,148,1,254,109,203, +156,202,203,156,202,254,109,1,147,202,156,0,1,0,48,255,253,4,161,4,111,0,23,0,0,9,1,7,1,17,35,17,1,39,1,33,53,33,1,55,1,17,51,17,1,23,1,33,21,2,197,1,80,54,254,176,77,254,176,54,1,80,254,36,1,221,254,175,54,1,80,77,1,80,54,254,175,1,221,2,16,254,175, +54,1,82,254,35,1,220,254,175,54,1,81,76,1,82,54,254,175,1,220,254,36,1,81,54,254,174,76,0,1,0,36,255,240,4,173,4,122,0,15,0,0,1,19,9,1,13,1,9,1,11,1,9,1,45,1,9,1,2,104,60,1,95,254,245,1,181,254,75,1,11,254,161,60,59,254,161,1,10,254,76,1,180,254,246, +1,95,4,122,254,75,1,11,254,161,60,59,254,160,1,12,254,74,1,182,254,244,1,96,59,60,1,95,254,245,0,0,9,0,26,255,233,4,183,4,134,0,2,0,5,0,8,0,11,0,14,0,17,0,20,0,23,0,39,0,0,1,15,1,33,39,7,1,47,1,17,55,39,1,63,1,33,23,55,1,31,1,17,7,23,17,19,37,3,13,1, +19,37,11,1,5,19,45,1,3,5,3,161,222,91,1,186,223,219,1,57,94,219,91,91,254,200,222,90,254,71,223,218,254,200,94,218,90,90,122,1,39,125,1,42,254,214,125,254,217,122,121,254,217,125,254,214,1,42,125,1,39,3,113,94,220,92,92,254,200,222,90,254,71,223,218, +254,200,94,218,90,90,1,58,222,92,1,187,223,220,2,79,254,214,125,254,216,122,121,254,217,125,254,214,1,42,125,1,39,121,122,1,40,125,0,0,0,0,1,0,50,255,228,4,159,5,0,0,11,0,0,1,19,37,9,1,37,11,1,5,9,1,5,2,104,95,1,216,254,135,1,121,254,40,95,94,254,40, +1,122,254,134,1,216,4,255,254,23,163,254,185,254,186,163,254,21,1,235,163,1,70,1,71,163,0,0,1,0,31,255,224,4,178,4,115,0,15,0,0,1,19,37,3,13,1,19,37,11,1,5,19,45,1,3,5,2,104,86,1,72,207,1,122,254,134,207,254,184,86,85,254,184,207,254,134,1,122,207,1, +72,4,114,254,134,207,254,184,86,85,254,184,207,254,133,1,123,207,1,72,85,86,1,72,207,0,0,1,0,26,255,234,4,183,4,134,0,15,0,0,1,19,37,3,13,1,19,37,11,1,5,19,45,1,3,5,2,104,130,1,31,104,1,21,254,235,104,254,225,130,129,254,225,104,254,235,1,21,104,1,31, +4,134,254,235,104,254,225,130,130,254,225,104,254,235,1,21,104,1,31,130,130,1,31,104,0,0,1,0,36,255,221,4,173,4,104,0,23,0,0,1,19,55,3,37,7,13,1,23,37,19,39,11,1,7,19,5,55,45,1,39,5,3,23,2,104,88,203,53,1,10,180,1,1,254,255,180,254,246,53,203,88,86,204, +54,254,245,179,255,0,1,0,179,1,11,54,204,4,103,254,255,179,254,246,53,203,86,87,204,54,254,246,179,254,255,1,1,179,1,10,54,204,87,86,203,53,1,10,179,0,0,1,0,48,0,2,4,161,4,116,0,47,0,0,1,17,51,17,19,23,3,55,23,7,37,23,5,33,21,33,5,7,37,23,7,39,19,7,3, +17,35,17,3,39,19,7,39,55,5,39,37,33,53,33,37,55,5,39,55,23,3,55,2,59,91,130,84,129,239,65,240,1,58,35,254,197,1,84,254,175,1,56,35,254,198,240,65,238,128,84,130,91,130,84,129,239,65,240,254,198,35,1,57,254,174,1,84,254,197,35,1,56,238,65,238,128,84,3, +32,1,84,254,174,1,56,35,254,199,240,65,240,130,84,131,91,129,85,131,241,64,238,254,200,35,1,55,254,175,1,83,254,199,35,1,57,239,64,239,129,85,129,91,131,84,129,239,65,239,1,56,35,0,0,1,0,49,255,240,4,160,4,232,0,159,0,0,1,53,52,39,38,53,52,55,54,50,23, +22,21,20,7,6,29,1,23,22,23,55,54,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,35,34,35,34,15,1,22,21,20,7,23,22,51,50,55,50,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,47,1,6,15,1,21,20,23,22,21,20,7,6,34,39,38,53,52,55,54,61,1,38,39,38,39, +7,6,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,54,51,50,51,22,51,50,63,1,38,53,52,55,39,38,35,34,35,34,35,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,31,1,54,55,54,2,63,62,36,44,46,99,46,44,36,62,13,25,20,8,93,53,32,55,49,43,18,17,58,25,16,4,11, +72,51,62,5,5,8,9,107,82,10,3,4,10,83,107,9,8,5,5,62,51,72,11,4,16,25,58,17,18,43,49,55,32,55,90,12,22,20,13,62,36,44,46,99,46,44,36,63,7,7,23,19,12,90,55,32,55,49,43,18,17,58,25,16,4,11,72,51,62,5,5,8,9,108,82,10,4,3,10,82,107,9,8,5,5,62,51,72,11,4,16, +25,58,17,18,43,49,55,32,57,88,9,22,23,7,2,248,10,105,98,57,64,82,39,41,41,39,82,64,57,100,103,10,5,11,19,5,56,100,60,32,28,5,20,43,28,36,18,20,59,41,29,48,5,16,16,18,16,6,49,1,30,41,58,20,18,36,29,42,20,5,28,32,60,103,52,7,21,7,5,13,104,99,57,64,82,40, +40,40,40,82,64,57,99,104,13,2,3,10,18,7,52,103,60,32,28,5,20,42,29,36,18,20,58,41,30,1,48,6,16,19,16,16,5,48,29,41,59,20,18,36,28,43,20,5,28,32,60,107,48,5,20,9,3,0,2,0,55,255,238,4,154,4,217,0,29,0,185,0,0,0,34,7,6,7,6,7,6,21,20,23,22,23,22,23,22,50, +55,54,55,54,55,54,53,52,39,38,39,38,47,1,53,52,39,38,53,52,55,54,50,23,22,21,20,7,6,29,1,23,22,23,55,54,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,43,1,34,35,34,15,1,22,21,20,7,23,22,51,50,59,1,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,47,1,6,15, +1,21,20,23,22,21,20,7,6,34,39,38,53,52,55,54,61,1,38,39,38,39,7,6,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,54,59,1,50,51,50,63,1,38,53,52,55,39,38,35,34,43,1,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,31,1,54,55,54,2,122,35,13,15,11,13,5,7,7, +5,13,11,15,13,35,13,15,11,13,5,7,7,5,13,11,15,72,61,36,44,46,97,46,44,36,62,13,25,20,8,92,53,31,55,48,43,18,17,57,25,16,4,12,70,51,61,10,9,8,107,81,10,4,4,9,83,106,9,8,10,61,51,70,12,4,16,25,57,17,18,43,48,55,31,55,89,12,22,20,13,62,36,44,46,97,46,44, +36,63,8,6,24,18,12,89,55,31,55,48,43,18,17,57,25,16,4,11,71,51,61,10,9,8,107,82,9,4,4,10,81,107,8,9,10,61,51,71,11,4,16,25,57,17,18,43,48,55,31,57,87,9,21,24,6,2,183,7,6,12,12,14,14,17,17,14,14,12,12,6,7,7,6,12,12,14,14,17,17,14,14,12,12,6,62,10,104, +96,57,64,81,39,40,40,39,81,64,57,98,102,10,5,11,19,5,55,99,60,31,29,6,19,43,28,36,18,19,58,41,29,47,6,15,16,17,17,5,48,30,40,58,19,18,36,28,43,19,6,29,31,60,102,51,7,21,7,5,12,103,99,56,64,81,39,40,40,39,81,64,56,99,103,12,3,2,11,17,7,51,102,60,31,29, +6,19,43,28,36,18,19,58,40,30,47,6,16,18,16,15,6,47,29,41,58,19,18,36,28,43,19,6,29,31,60,105,48,5,20,9,3,0,1,0,52,255,235,4,150,4,223,0,106,0,0,1,39,38,7,6,39,38,39,38,55,54,55,54,23,22,23,22,31,1,53,52,39,38,53,52,55,54,50,23,22,21,20,7,6,29,1,55,54, +55,54,55,54,23,22,23,22,7,6,7,6,39,38,15,1,23,22,55,54,23,22,23,22,7,6,7,6,39,38,39,38,47,1,21,20,23,22,21,20,7,6,35,34,39,38,53,52,55,54,61,1,7,6,7,6,7,6,39,38,39,38,55,54,55,54,23,22,55,2,18,38,40,151,90,68,76,14,23,34,35,90,58,76,71,35,58,46,39,87, +52,44,67,138,67,44,52,87,39,39,65,40,67,75,59,90,34,34,23,14,76,71,87,144,47,39,39,39,152,91,67,76,14,23,34,36,88,62,72,72,35,58,46,39,87,52,44,67,69,72,64,44,52,87,39,42,62,38,68,76,58,90,35,35,24,15,75,71,87,147,44,2,102,22,23,13,8,39,44,59,91,59,59, +26,17,43,42,81,132,27,23,45,45,125,75,79,87,42,65,65,42,87,83,71,117,53,45,23,23,136,85,38,43,17,26,59,59,91,59,44,41,10,16,26,22,23,23,13,7,39,43,59,91,60,62,23,16,42,42,81,133,27,22,45,45,125,75,78,87,43,64,64,45,85,83,70,117,53,45,22,25,135,83,40, +43,17,26,59,62,89,59,43,42,10,16,26,0,0,0,4,0,33,255,229,4,176,4,189,0,14,0,153,0,177,0,201,0,0,1,54,55,54,53,52,39,38,34,7,6,21,20,23,22,19,23,22,51,50,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,47,1,21,20,23,22,21,20,7,6,35,34,39,38,53, +52,55,54,61,1,7,6,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,51,50,63,1,39,38,35,34,7,6,35,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,31,1,53,52,39,38,53,52,55,54,50,23,22,21,20,7,6,29,1,55,54,55,54,55,54,51,50,23,22,23,22,21,20, +7,6,7,6,35,34,39,38,35,34,7,5,6,35,34,39,38,35,34,7,6,7,6,21,20,23,22,23,22,51,50,55,54,55,54,37,22,23,22,23,22,51,50,55,54,55,54,53,52,39,38,39,38,35,34,7,6,35,34,2,105,23,47,31,25,41,70,41,26,31,47,141,15,44,85,27,31,15,14,75,58,77,15,10,21,36,92,16, +18,47,56,69,40,53,62,15,72,54,45,69,70,74,65,45,53,72,15,59,56,41,68,55,46,19,17,92,35,21,9,16,76,59,75,14,15,30,27,85,44,16,16,42,85,28,31,15,14,75,59,75,17,10,22,35,92,17,19,46,55,70,39,53,62,15,72,53,45,68,141,69,45,54,72,15,60,55,42,67,56,47,18,16, +92,36,21,10,15,77,58,75,14,15,32,27,85,43,254,211,58,54,25,24,8,8,45,50,49,6,4,11,17,52,9,10,26,36,58,21,30,1,143,60,30,21,59,36,26,10,8,52,18,11,4,6,50,50,45,8,7,25,25,54,3,12,79,59,40,65,55,20,35,35,20,55,65,40,59,254,247,9,26,3,1,33,42,58,35,31,46, +35,59,24,4,30,38,82,109,33,8,16,67,99,74,77,85,41,63,63,44,82,77,74,99,67,16,8,31,111,83,37,31,5,26,57,35,46,31,35,59,41,33,1,3,26,9,8,25,2,1,32,41,59,35,31,45,36,58,25,5,30,39,81,110,33,8,16,68,99,73,77,85,42,63,63,42,85,77,73,99,68,16,8,32,111,83,37, +30,5,24,59,35,46,30,36,58,42,32,1,2,25,102,14,3,1,28,27,31,20,16,27,18,29,16,3,19,32,47,68,59,59,68,47,32,19,3,16,29,18,27,16,20,31,27,28,1,3,0,0,2,0,36,0,0,4,173,4,105,0,29,0,141,0,0,0,34,7,6,7,6,7,6,21,20,23,22,23,22,23,22,50,55,54,55,54,55,54,53,52, +39,38,39,38,39,55,54,55,54,51,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,39,38,39,38,39,6,7,6,7,6,7,6,35,34,39,38,39,38,39,38,53,52,55,54,55,54,55,6,35,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,51, +50,23,22,23,38,39,38,53,52,55,54,55,54,55,54,51,50,23,22,23,22,23,22,21,20,7,6,2,160,111,48,48,39,41,19,20,20,19,41,39,48,48,111,48,48,39,41,19,20,20,19,41,39,48,93,48,29,43,41,42,43,37,35,32,18,16,16,15,35,29,43,37,48,22,21,37,26,35,14,17,17,18,31,35, +38,38,46,48,37,43,29,37,13,10,4,3,11,18,32,35,37,39,46,48,36,44,28,35,15,16,16,19,31,29,28,18,19,48,37,45,27,35,15,16,16,18,32,35,37,39,46,48,36,46,32,6,5,16,16,18,32,35,37,39,45,49,36,44,28,35,15,16,16,5,3,36,20,22,37,42,47,48,57,54,49,47,42,37,22,20, +20,22,37,42,47,49,54,57,48,47,42,37,22,15,41,12,18,18,15,34,30,42,38,48,45,40,37,36,29,19,17,4,18,26,36,36,41,45,48,38,42,30,33,16,16,16,20,29,38,34,27,28,29,26,42,30,33,16,16,16,20,29,36,36,41,45,48,38,45,27,26,17,4,17,21,28,35,37,40,45,48,38,42,30, +34,15,17,17,19,34,11,11,40,45,48,38,42,30,34,15,16,16,19,30,36,36,40,46,47,38,11,0,6,0,22,0,3,4,187,4,134,0,110,0,138,0,163,0,191,0,216,0,244,0,0,37,6,7,6,7,6,7,6,35,34,39,38,39,38,39,38,53,52,55,54,55,54,55,6,35,34,39,38,39,38,39,38,53,52,55,54,55,54, +55,54,51,50,23,22,23,38,39,38,53,52,55,54,55,54,55,54,50,23,22,23,22,23,22,21,20,7,6,7,54,55,54,51,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,39,38,39,38,2,50,23,22,23,55,54,53,52,39,38,39,38,39,38,34, +7,6,7,6,7,6,21,20,31,1,54,55,19,38,39,38,39,38,39,7,6,7,6,21,20,23,22,23,22,23,22,50,55,54,55,54,55,3,38,53,52,55,54,55,39,38,39,38,35,34,7,6,7,6,7,6,21,20,23,22,23,22,23,22,23,5,23,22,23,22,23,22,50,55,54,55,54,55,54,53,52,39,38,47,1,6,7,6,7,6,63,1, +54,55,54,55,54,55,54,53,52,39,38,39,38,39,38,35,34,7,6,15,1,22,23,22,21,20,2,104,3,11,13,38,29,44,38,49,47,40,38,35,33,18,17,17,15,36,26,38,22,23,49,37,45,29,36,15,17,17,18,33,38,36,47,39,46,41,29,50,6,5,16,16,15,36,29,45,37,99,37,45,29,36,15,16,16,5, +6,50,29,45,42,43,43,38,36,33,18,17,17,15,36,29,45,37,49,23,22,38,26,36,15,17,17,18,33,35,38,40,47,49,38,44,29,38,13,11,61,115,48,6,6,14,7,10,9,22,20,25,24,57,24,25,20,22,9,10,7,14,6,6,53,28,25,53,37,24,21,82,19,12,10,10,10,21,20,25,24,57,24,26,19,19, +12,178,3,21,17,33,95,7,5,28,25,28,24,25,20,19,12,11,11,9,22,20,25,17,12,1,186,44,12,19,19,26,24,57,24,25,20,21,10,10,10,12,19,82,21,24,37,53,25,194,115,12,17,25,20,22,9,11,11,12,19,20,25,24,28,25,28,5,7,95,33,17,21,200,29,27,35,39,30,20,17,17,16,34,31, +43,39,48,47,41,38,36,27,19,4,16,20,30,37,37,41,46,50,39,43,31,36,14,18,18,13,42,10,11,39,49,46,42,37,37,30,20,16,16,20,30,37,37,42,46,49,39,11,10,42,13,18,18,16,34,31,43,39,50,46,41,37,37,30,20,16,4,19,27,36,38,41,47,48,39,43,31,34,16,17,17,20,30,39, +35,27,2,142,20,3,3,76,37,16,28,26,24,21,19,11,11,11,11,19,21,24,26,28,16,37,76,3,3,253,236,5,11,24,37,23,35,77,19,27,25,29,28,25,24,21,19,11,11,11,11,19,19,26,1,76,17,19,58,50,40,38,54,3,2,10,10,11,19,19,26,23,31,28,26,23,22,19,11,7,2,251,95,26,19,19, +11,11,11,11,19,21,24,25,28,29,25,27,19,77,35,23,37,24,11,232,14,2,7,11,19,22,23,26,28,31,23,26,19,19,11,10,10,2,3,54,38,40,50,58,19,0,0,10,0,22,255,237,4,187,4,148,0,45,0,91,0,213,1,4,1,51,1,98,1,145,1,175,1,221,2,11,0,0,1,38,39,7,6,35,34,39,38,39,38, +39,38,53,52,55,54,55,54,55,54,51,50,31,1,54,55,39,38,35,34,6,7,6,7,6,20,23,22,23,22,23,22,51,50,55,37,6,7,23,22,51,50,55,54,55,54,55,54,52,39,38,39,46,1,35,34,15,1,22,23,55,54,51,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,37,38,39,38,53,52,55,54, +55,54,55,54,51,50,23,22,23,52,54,55,54,55,54,50,23,22,23,30,1,21,54,55,54,51,50,23,22,23,22,23,22,21,20,7,6,7,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,39,20,6,7,6,7,6,34,39,38,39,46,1,53,6,7,6,35,34,39,38,39,38, +39,38,53,52,55,54,55,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,1,38,39,7,6,7,6,7,6,7,38,39,38,39,38,39,38,39,54,55,54,55,54,63,1,38,39,7,6,7,6,7,6,21,22,23,22,23,30,1,51,50,55,54,55,54,55,1,22,23,55,54,55,54,55,54,53,38,39,38,39,46,1,35,34,7,6,7,6, +15,1,22,23,55,54,55,54,55,54,55,22,23,22,23,22,23,22,23,6,7,6,7,6,7,3,6,7,23,22,23,22,23,22,23,6,7,6,7,6,7,6,7,38,39,38,39,38,47,1,6,7,23,22,23,22,23,22,51,50,54,55,54,55,54,55,52,39,38,39,38,39,1,54,55,39,38,39,38,39,38,35,34,6,7,6,7,6,7,20,23,22,23, +22,31,1,54,55,39,38,39,38,39,38,39,54,55,54,55,54,55,54,55,22,23,22,23,22,23,4,34,7,6,7,6,7,6,21,20,23,22,23,22,23,22,50,55,54,55,54,55,54,53,52,39,38,39,38,39,19,6,7,23,22,21,20,7,6,7,6,7,6,34,39,38,39,38,39,38,53,52,63,1,38,39,7,6,21,20,23,22,23,22, +23,22,50,55,54,55,54,55,54,53,52,39,3,22,23,55,54,53,52,39,38,39,38,39,38,34,7,6,7,6,7,6,21,20,31,1,54,55,39,38,53,52,55,54,55,54,55,54,50,23,22,23,22,23,22,21,20,7,1,139,4,2,175,13,7,7,11,9,8,6,5,3,3,5,6,8,9,9,9,7,13,175,2,4,158,27,16,21,40,17,15,10, +7,7,10,15,17,20,20,21,16,27,2,98,2,4,155,27,14,23,20,20,17,15,10,7,7,10,15,17,40,23,14,27,155,4,2,172,13,5,13,7,9,8,6,5,3,3,5,6,9,8,11,9,5,13,252,205,28,13,13,13,12,25,25,31,31,35,33,34,31,28,26,25,25,30,31,71,31,30,25,25,26,30,29,34,33,35,31,31,25,22, +15,13,13,11,30,42,30,29,26,27,11,13,13,13,25,21,34,32,39,29,11,13,13,12,25,25,31,31,35,35,32,31,28,26,25,25,30,31,71,31,30,25,25,26,31,28,33,34,34,32,31,25,25,12,13,13,13,27,39,32,29,26,27,12,12,12,14,25,26,29,30,1,89,15,13,109,8,5,5,10,9,11,10,9,9,7, +7,4,3,1,1,4,3,7,4,11,138,11,8,141,26,10,17,7,9,1,8,7,17,16,40,22,24,19,20,16,11,14,1,121,12,7,139,26,10,17,7,9,1,8,7,17,16,40,22,24,19,20,17,10,14,79,15,13,107,8,4,8,8,9,11,10,9,9,7,7,4,3,1,1,4,4,6,4,11,119,8,11,138,11,4,6,4,4,1,1,3,4,7,7,9,9,10,11,9, +8,7,5,8,109,13,15,81,14,11,16,20,19,24,22,40,16,17,7,8,1,9,7,17,10,26,254,28,14,14,79,14,10,17,20,19,24,22,40,16,17,7,8,1,9,7,17,10,26,139,8,11,136,11,4,7,3,4,1,1,3,4,7,7,9,9,10,13,7,10,6,4,8,1,26,63,27,27,23,22,12,11,11,12,22,23,27,27,63,27,27,23,22, +12,11,11,12,22,23,27,2,17,16,21,1,3,4,7,8,8,10,19,10,8,8,7,4,3,1,21,17,16,43,8,9,7,17,16,20,19,47,19,20,16,17,7,9,8,76,18,16,42,8,9,7,17,16,20,19,47,19,20,16,17,7,9,8,42,17,17,21,1,3,4,7,8,8,10,19,10,8,8,8,3,3,1,2,3,17,17,21,2,5,3,7,8,8,9,11,9,9,9,8, +6,5,3,2,20,17,16,43,7,15,17,17,20,18,46,20,20,16,16,8,9,7,77,18,16,43,7,9,8,16,16,20,20,46,18,20,17,17,15,7,42,17,17,20,2,3,5,6,8,9,9,9,11,9,8,8,9,1,5,2,221,28,32,33,33,33,33,31,25,25,12,13,13,13,27,39,63,24,24,14,13,13,14,24,24,63,39,29,11,13,13,12, +25,22,34,31,35,28,38,31,29,13,12,26,27,28,31,35,39,27,31,25,23,15,14,29,30,34,33,33,32,31,25,25,13,12,12,13,28,39,63,25,23,14,13,13,14,23,25,63,39,30,11,12,12,13,25,25,31,32,33,34,33,32,27,14,12,26,27,29,30,36,38,28,31,24,26,12,13,254,140,9,10,139,10, +4,6,4,4,1,1,3,4,7,7,9,9,10,10,9,10,6,5,8,109,13,14,80,15,11,15,20,19,24,22,21,19,17,16,15,7,9,15,11,25,1,229,13,15,79,15,10,16,20,19,24,22,21,19,17,16,15,7,9,16,10,25,139,9,11,136,10,4,9,2,4,1,1,3,4,7,7,9,9,10,13,6,10,7,4,8,254,147,14,13,109,8,5,6,10, +9,10,10,9,9,7,7,4,3,1,1,4,3,7,4,10,139,11,8,142,25,11,15,9,7,15,16,17,19,21,22,24,19,20,15,11,15,1,121,11,9,139,25,10,16,9,7,15,16,17,19,21,22,24,19,20,16,10,15,79,15,13,107,8,4,8,9,9,10,10,9,9,7,7,4,3,1,1,4,4,7,4,10,163,12,12,21,24,26,28,31,31,28,27, +23,21,12,12,12,12,21,23,27,28,31,31,28,26,24,21,12,254,147,5,1,175,13,7,8,10,9,8,7,4,3,3,4,7,8,9,9,9,7,13,175,1,5,158,28,15,22,20,19,17,15,9,9,9,9,15,17,19,20,22,15,28,2,98,1,5,154,29,14,23,20,19,17,15,9,9,9,9,15,17,19,20,23,14,29,154,5,1,172,13,6,11, +8,9,8,7,3,4,4,3,7,10,7,10,9,6,13,0,0,0,0,4,0,37,255,223,4,172,4,106,0,29,0,60,0,92,0,108,0,0,0,34,7,6,7,6,7,6,21,20,23,22,23,22,23,22,50,55,54,55,54,55,54,53,52,39,38,39,38,47,1,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,39,38,39,38,52,55,54, +55,54,55,54,19,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,23,3,37,19,13,1,3,37,27,1,5,3,45,1,19,5,2,150,91,39,39,33,32,16,16,16,16,32,33,39,39,91,38,40,32,33,16,16,16,16,33,32,40,84,66,51,57,41,43,24,23,23, +23,44,43,55,54,63,65,51,58,40,43,24,23,23,23,44,43,55,54,62,116,106,101,86,84,44,43,43,40,88,82,105,105,117,115,107,100,86,84,44,42,42,40,88,81,105,106,116,117,254,223,122,254,222,1,34,122,1,33,117,118,1,33,122,1,34,254,222,122,254,223,3,4,17,18,30,35, +38,40,44,45,39,39,34,30,18,17,17,18,30,34,39,39,45,44,40,38,35,30,18,101,24,25,41,42,58,54,63,59,57,55,44,43,23,24,24,25,41,42,57,55,122,56,56,44,43,23,24,1,17,44,42,85,84,104,103,121,114,105,99,89,84,43,44,44,42,85,83,105,103,116,118,106,98,90,82,45, +44,6,254,222,122,254,223,118,118,254,224,122,254,222,1,34,122,1,32,118,118,1,33,122,0,0,0,7,0,50,255,237,4,159,5,57,0,8,0,147,0,156,0,167,0,178,0,193,0,208,0,0,1,17,34,7,6,21,20,23,22,19,23,22,51,50,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39, +38,47,1,21,20,23,22,21,20,7,6,35,34,39,38,53,52,55,54,61,1,7,6,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,51,50,63,1,39,38,35,34,7,6,35,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,31,1,53,52,39,38,53,52,55,54,50,23,22,21,20,7,6,29, +1,55,54,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,35,34,15,1,17,50,55,54,53,52,39,38,19,37,38,39,38,35,34,7,6,7,6,1,5,22,23,22,51,50,55,54,55,54,19,37,6,21,20,23,22,23,22,51,50,55,54,51,50,13,1,54,53,52,39,38,39,38,35,34,7,6,35,34,2,105, +34,40,25,31,45,137,14,43,83,25,30,15,13,73,57,75,14,9,20,35,89,16,17,46,54,67,38,52,60,14,70,52,44,67,68,72,63,44,52,70,15,57,54,40,66,53,45,18,17,89,34,21,9,15,75,56,73,14,14,30,26,83,42,15,15,41,82,27,31,14,14,73,56,74,16,9,21,34,89,17,18,45,53,68, +38,51,60,15,70,52,44,67,136,67,44,52,70,14,58,54,40,65,54,46,17,16,89,35,20,9,14,75,57,73,13,15,30,27,82,42,128,34,40,24,30,45,141,1,54,17,50,8,10,25,35,57,20,30,254,126,254,201,17,51,8,10,25,35,57,20,29,59,254,201,10,4,5,48,49,43,8,8,23,24,53,1,128, +1,54,11,4,6,48,48,44,8,7,24,24,53,3,96,1,129,37,23,59,71,44,65,254,222,10,28,3,1,36,46,63,39,33,51,38,64,27,5,33,42,89,120,36,9,18,73,109,80,84,93,45,69,69,48,90,84,80,109,73,18,9,34,122,90,41,33,5,28,63,38,51,33,39,64,45,36,1,3,28,10,9,28,3,1,35,44, +65,39,33,50,39,63,28,5,33,42,89,120,36,8,17,73,109,81,84,92,46,69,69,46,92,84,81,109,73,17,8,35,121,90,41,33,5,26,65,38,50,34,39,63,46,35,1,3,28,214,254,126,38,22,60,71,44,64,1,137,193,32,18,4,22,35,51,74,254,243,193,32,18,3,21,35,51,74,1,13,193,19,30, +17,22,34,30,30,1,4,220,193,20,29,18,21,34,30,30,1,3,0,1,0,32,0,2,4,177,5,87,0,65,0,0,1,39,7,39,55,39,55,23,53,51,21,23,53,39,55,23,53,51,21,55,23,7,21,55,53,51,21,55,23,7,23,7,39,7,23,55,23,7,23,7,39,21,35,53,39,21,23,7,39,21,35,53,7,39,55,53,7,21,35, +53,7,39,55,39,55,23,2,1,207,168,52,116,169,52,169,104,207,168,52,116,103,116,52,168,207,104,169,52,169,116,52,168,207,207,168,52,116,169,52,169,104,207,168,52,116,103,116,52,168,207,104,169,52,169,116,52,168,2,173,126,102,95,70,104,96,105,142,205,127, +254,102,95,71,208,208,71,95,102,253,126,205,142,105,96,104,70,95,102,126,127,102,95,70,104,95,104,142,205,127,254,102,95,71,208,208,71,95,102,254,127,205,142,104,95,104,70,95,102,0,7,0,48,255,250,4,161,4,179,0,29,0,33,0,37,0,41,0,45,0,49,0,53,0,0,1,51, +21,55,17,55,23,7,23,7,23,7,39,17,39,21,35,53,7,17,7,39,55,39,55,39,55,23,17,23,7,21,23,53,55,7,21,55,5,7,23,55,37,7,23,55,5,7,21,63,1,21,23,53,2,56,97,236,214,49,216,237,236,215,49,214,236,97,236,214,49,215,236,237,216,49,214,236,138,138,235,138,138, +254,91,139,138,138,1,76,137,138,138,254,90,138,138,97,138,4,179,249,136,254,240,125,84,125,136,136,123,85,125,254,239,137,248,248,137,1,17,125,85,123,136,136,125,84,125,1,16,136,32,159,80,159,80,80,159,80,85,80,79,79,80,80,79,79,83,80,160,80,160,160, +80,160,0,0,0,1,0,25,0,5,4,184,4,192,0,65,0,0,1,51,21,55,23,7,21,55,53,51,21,55,23,7,23,7,39,7,23,55,23,7,23,7,39,21,35,53,39,21,23,7,39,21,35,53,7,39,55,53,7,21,35,53,7,39,55,39,55,23,55,39,7,39,55,39,55,23,53,51,21,23,53,39,55,23,2,57,97,114,81,195, +218,162,72,49,74,113,81,195,216,217,195,81,114,73,49,75,162,214,195,81,114,97,114,81,195,216,162,74,49,72,114,81,195,217,215,195,82,114,75,49,73,162,219,195,81,114,4,191,84,66,141,113,249,126,226,132,42,84,43,66,141,112,124,126,113,141,65,43,84,43,131, +225,124,247,113,141,66,84,82,66,140,113,251,124,225,131,43,84,42,65,142,113,125,124,113,141,66,43,84,41,131,225,126,252,112,141,66,0,0,0,0,1,0,50,255,238,4,159,4,216,0,135,0,0,1,22,21,20,7,6,7,6,35,34,39,38,39,7,23,54,55,54,51,50,23,22,23,22,21,20,7, +6,7,6,35,34,39,38,39,38,53,52,55,39,21,22,23,30,1,20,14,1,34,46,1,52,54,55,54,55,53,7,22,21,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,55,39,6,7,6,35,34,46,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,23,53,38,39,46,1,52,54,55,54,51,50, +30,1,20,6,7,6,7,21,55,38,53,52,55,54,55,54,51,50,23,22,4,137,22,22,22,37,39,43,44,37,15,14,196,196,14,15,37,44,43,39,37,22,22,22,23,36,39,43,41,40,38,22,21,3,196,17,16,37,44,44,75,87,75,44,44,37,16,17,196,3,21,22,38,38,43,44,38,37,22,22,22,22,37,39,86, +38,15,14,196,196,13,16,40,41,44,75,44,22,22,37,39,43,41,40,38,22,21,3,196,17,16,37,44,44,37,38,43,44,75,44,44,37,16,17,196,3,21,21,39,37,44,43,39,41,3,157,44,37,43,39,37,22,22,22,9,12,113,113,12,9,22,22,22,38,38,43,42,38,38,22,22,22,21,38,37,44,18,17, +114,227,6,8,22,75,88,75,44,44,75,88,75,22,8,6,227,114,17,18,44,37,38,21,22,22,21,38,37,44,43,38,38,22,22,22,9,12,113,113,12,9,22,44,75,88,37,38,21,22,22,21,38,37,44,18,17,114,227,5,9,22,75,88,75,21,22,43,75,88,75,22,9,5,227,114,17,18,44,37,36,23,22,22, +24,0,0,9,0,41,255,235,4,168,4,106,0,7,0,11,0,15,0,19,0,23,0,46,0,69,0,92,0,115,0,0,0,20,6,34,38,52,54,50,9,1,55,9,2,55,1,37,1,39,9,2,39,1,55,38,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,3,22,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,53, +52,55,54,55,54,39,6,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,5,54,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,2,218,67,93,67,67,93,1,64,254,220,64,1,36,253,198,254,221,64,1,35,1,250,254,220,64,1,36,254,70,254,221,64,1, +35,139,43,11,17,3,1,1,3,11,17,87,17,11,3,1,1,3,17,11,44,44,11,17,3,1,1,3,11,17,87,17,11,3,1,1,3,17,11,120,45,18,28,51,22,62,52,23,49,24,37,37,24,49,23,52,62,22,51,28,18,1,116,45,18,28,51,22,62,52,23,49,24,37,37,24,49,23,52,62,22,51,28,18,2,102,94,67, +67,94,66,253,223,1,37,64,254,219,1,186,1,35,64,254,221,227,254,219,64,1,37,253,198,254,221,64,1,35,228,45,18,28,52,21,62,52,23,49,24,37,37,24,49,23,52,62,21,52,28,18,254,140,45,18,28,51,22,62,52,23,49,24,37,37,24,49,23,52,62,22,51,28,18,209,43,12,17, +3,1,2,2,11,18,86,17,11,3,1,1,3,17,11,43,43,11,17,3,1,1,3,11,17,86,18,11,2,2,1,3,17,12,0,0,9,0,33,255,227,4,176,4,114,0,7,0,11,0,15,0,19,0,23,0,43,0,63,0,83,0,103,0,0,0,20,6,34,38,52,54,50,1,55,23,7,1,55,23,7,1,23,7,39,1,23,7,39,2,20,7,6,7,6,34,39,38, +39,38,52,55,54,55,54,50,23,22,23,18,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,50,23,22,23,0,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,52,55,54,55,36,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,52,55,54,55,3,21,101,143,101,101,143,254,4,227,66,228,2,3,228, +65,227,253,187,228,66,227,2,134,227,65,228,6,14,16,30,35,85,35,30,16,14,14,16,30,35,85,35,30,16,14,14,16,30,35,85,35,30,16,14,14,16,30,35,85,35,30,16,253,199,86,37,42,27,31,31,27,42,37,86,38,42,27,30,30,27,42,3,75,86,38,42,27,30,30,27,42,38,86,37,42, +27,31,31,27,42,2,126,142,102,102,142,101,253,223,227,65,227,2,134,227,65,227,1,36,227,65,227,253,252,227,65,227,2,132,86,37,42,27,31,31,27,42,37,86,38,42,27,30,30,27,42,252,181,86,38,42,27,30,30,27,42,38,86,37,42,27,31,31,27,42,1,204,14,16,30,35,85,35, +30,16,14,14,16,30,35,85,35,30,16,14,14,16,30,35,85,35,30,16,14,14,16,30,35,85,35,30,16,0,0,0,0,9,0,23,255,234,4,186,4,141,0,12,0,25,0,38,0,51,0,64,0,77,0,89,0,97,0,109,0,0,1,20,7,6,43,1,37,53,37,51,50,23,22,5,52,55,54,59,1,5,21,5,35,34,39,38,1,22,21, +20,15,2,39,63,1,54,51,50,1,38,53,52,63,2,23,15,1,6,35,34,3,54,51,50,31,2,7,47,1,38,53,52,1,6,35,34,47,2,55,31,1,22,21,20,0,50,23,22,29,1,3,35,3,53,52,55,18,20,6,34,38,52,54,50,2,34,39,38,61,1,19,51,19,21,20,7,4,185,21,22,30,8,254,193,1,63,8,29,23,21, +251,95,21,22,30,8,1,63,254,193,8,29,23,21,3,244,22,20,6,252,54,198,5,21,32,32,252,207,22,20,6,252,54,198,5,21,32,30,24,22,32,31,22,5,198,54,252,6,20,3,93,23,31,32,21,5,198,54,252,6,20,254,39,63,23,22,38,77,38,22,169,67,95,67,67,95,16,63,23,22,38,77,38, +22,2,60,32,23,22,39,76,38,22,23,31,31,23,22,38,76,39,22,23,1,195,22,33,30,22,5,198,54,252,5,22,252,162,23,32,30,22,5,198,54,252,5,22,3,94,23,22,5,252,54,198,5,21,31,33,252,207,23,22,5,252,54,198,5,21,31,32,3,222,23,21,31,7,254,194,1,62,7,30,22,253,245, +95,67,67,95,68,253,60,22,21,31,7,1,62,254,194,7,30,22,0,0,0,1,0,34,255,233,4,175,4,27,0,108,0,0,1,50,23,22,21,20,7,3,19,54,55,54,51,50,23,22,21,20,7,6,7,5,37,54,51,50,23,22,20,7,6,35,34,39,37,5,22,51,22,21,20,7,6,35,34,39,38,39,3,19,22,21,20,7,6,34,39, +38,53,52,55,19,3,6,7,6,35,34,39,38,53,52,55,50,55,37,5,6,35,34,39,38,52,55,54,51,50,23,5,37,38,39,38,53,52,55,54,51,22,23,22,23,19,3,38,53,52,55,54,2,104,33,35,27,4,59,214,15,2,39,38,49,24,22,39,8,18,254,219,1,104,19,9,57,26,35,35,27,56,5,28,254,157, +1,41,21,1,39,22,24,49,33,44,8,13,210,59,4,27,35,65,35,27,4,59,210,13,8,39,38,49,24,22,39,1,21,1,41,254,157,28,5,56,27,35,35,26,57,9,19,1,104,254,219,18,8,39,22,24,49,27,50,2,15,214,59,4,27,35,4,26,32,24,52,5,21,254,181,1,16,20,1,37,22,21,46,38,33,6,12, +194,54,3,23,32,61,32,25,4,54,196,16,37,34,46,21,22,37,7,17,1,13,254,181,21,5,51,25,32,32,25,51,9,21,1,71,254,243,17,7,37,22,21,46,53,18,16,196,54,4,25,32,61,32,23,3,54,194,12,6,37,34,46,21,22,14,23,1,20,254,240,1,71,21,9,52,24,32,0,0,0,2,0,36,255,245, +4,173,4,56,0,11,0,33,0,0,19,20,0,32,0,53,52,46,1,34,14,1,1,6,35,34,0,53,52,18,36,51,50,23,54,51,50,4,18,21,20,0,35,34,95,1,28,1,148,1,28,130,233,246,233,130,2,9,18,18,224,254,192,147,1,6,135,18,18,18,17,138,1,6,146,254,192,226,17,2,22,201,254,227,1,29, +201,128,232,126,126,232,253,97,1,1,62,226,141,1,7,141,1,1,141,254,251,143,226,254,194,0,0,0,0,2,0,69,255,193,4,140,4,9,0,3,0,11,0,0,37,17,33,17,23,35,17,33,21,51,17,33,4,14,252,112,12,69,4,2,69,251,254,63,3,144,252,112,57,4,2,69,251,255,0,0,0,2,0,61, +0,0,4,148,4,86,0,3,0,11,0,0,37,17,33,17,37,21,33,17,51,53,33,17,4,20,252,99,3,215,251,240,69,4,16,58,3,156,252,100,12,70,4,16,70,251,240,0,0,2,0,56,255,184,4,153,4,25,0,3,0,9,0,0,37,17,33,17,7,17,33,23,17,33,4,24,252,91,58,4,25,70,251,252,58,3,164,252, +92,59,4,25,91,251,252,0,0,2,0,48,0,0,4,161,4,113,0,3,0,9,0,0,37,17,33,17,5,33,17,55,33,17,4,30,252,78,3,237,251,215,93,4,20,60,3,178,252,78,59,4,41,71,251,237,0,4,0,43,255,250,4,166,4,116,0,3,0,7,0,11,0,15,0,0,19,9,14,44,1,3,1,4,254,252,1,111,1,4,1,3, +254,253,253,196,1,4,1,4,254,252,254,252,1,4,1,4,254,252,2,57,1,3,254,253,254,252,1,4,1,2,254,254,254,251,2,59,1,5,254,251,254,253,254,146,1,4,254,252,254,252,0,0,0,1,2,27,255,12,2,182,5,156,0,3,0,0,1,17,35,17,2,182,155,5,156,249,113,6,143,0,0,1,1,205, +255,10,3,4,5,153,0,3,0,0,1,17,33,17,3,3,254,203,5,153,249,114,6,142,0,1,1,81,254,203,3,128,5,107,0,3,0,0,1,17,33,17,3,127,253,211,5,107,249,96,6,160,0,1,1,221,3,207,2,244,5,217,0,6,0,0,1,33,17,55,51,7,51,2,244,254,233,125,98,62,118,3,207,1,23,243,243, +0,0,1,1,211,3,196,2,254,5,199,0,6,0,0,1,33,17,7,35,55,35,1,212,1,41,133,105,67,126,5,198,254,238,239,239,0,255,255,1,0,3,207,3,209,5,217,16,39,11,60,0,221,0,0,16,7,11,60,255,35,0,0,0,0,255,255,0,246,3,196,3,219,5,199,16,39,11,61,0,221,0,0,16,7,11,61, +255,35,0,0,0,0,0,2,0,103,255,93,4,106,5,129,0,79,0,83,0,0,1,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,7,6,7,6,7,6,20,23,22,23,22,23,22,51,50,55,54,55,54,55,54,53,17,35,34,39,38,53,52,54,59,1,53,55,21,33,7,35,17,20,7,6,7,6,7,6,35,34,39,38,39,38,39, +38,53,52,55,54,55,54,55,54,37,17,35,17,1,185,25,21,22,18,17,10,8,8,10,17,18,22,21,21,23,16,15,13,14,6,7,8,8,13,16,13,19,26,52,50,59,37,45,20,22,250,180,110,96,212,174,250,114,1,21,114,163,30,35,50,54,65,64,58,86,55,58,36,41,18,19,19,21,38,31,55,46,1, +89,155,1,113,9,10,17,16,24,22,25,24,22,24,16,17,10,9,7,6,13,13,16,16,37,17,18,11,15,5,7,22,27,36,46,50,55,55,1,29,103,91,149,154,189,163,40,203,100,252,162,86,68,81,52,57,31,30,20,21,37,42,44,48,52,63,40,41,45,35,23,20,250,1,230,254,26,0,0,2,0,255,255, +217,3,210,4,201,0,23,0,53,0,0,1,50,23,22,23,22,23,22,21,20,7,6,7,38,39,38,53,52,55,54,55,54,55,54,18,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,34,39,38,39,38,39,38,53,52,55,54,55,54,55,2,104,130,99,34,36,31,15,16,110,145,106,108,142,110,16,15,31,30,40,76, +102,101,42,43,36,36,18,17,17,18,36,36,43,42,101,42,43,36,37,17,17,17,17,37,36,43,4,201,33,11,35,31,39,40,42,100,82,106,168,168,106,83,99,42,40,39,31,29,17,33,252,249,18,20,34,37,42,44,50,48,44,43,37,34,20,17,17,20,34,37,43,44,48,50,44,42,37,34,20,0,0, +0,2,0,190,255,227,4,19,4,211,0,37,0,67,0,0,1,38,39,38,53,52,55,54,55,54,55,54,50,23,22,23,22,23,22,21,52,55,54,55,54,55,54,50,23,22,23,22,23,22,21,20,7,6,2,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,34,39,38,39,38,39,38,53,52,55,54,55,54,55,2,104,99,216, +110,16,15,31,30,40,37,88,37,38,31,30,16,16,17,16,30,31,38,38,87,37,40,30,31,15,16,110,216,150,101,42,43,36,36,18,17,17,18,36,36,43,42,101,42,43,36,37,17,17,17,17,37,36,43,2,44,159,131,68,106,42,40,39,31,29,17,16,16,16,30,30,40,38,44,44,38,40,30,30,16, +16,16,17,29,31,39,40,42,107,67,131,255,0,17,20,34,38,42,44,49,49,44,42,37,35,19,18,18,19,35,37,42,44,49,49,44,42,38,34,20,0,0,0,0,1,0,46,0,105,4,163,4,15,0,37,0,0,37,38,37,38,53,52,55,54,55,54,55,54,50,23,22,23,22,23,22,21,52,55,54,55,54,55,54,50,23, +22,23,22,23,22,21,20,7,4,2,104,104,254,195,148,21,21,42,40,52,50,117,50,52,41,40,22,21,22,22,40,41,52,50,117,50,52,40,42,21,21,148,254,195,105,194,197,92,144,61,57,55,44,42,25,23,23,24,43,42,57,54,64,64,54,57,42,43,24,23,23,25,42,44,55,57,61,146,90,197, +0,0,1,0,114,255,251,4,95,5,25,0,39,0,0,1,6,3,6,35,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,51,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,51,50,23,18,4,95,209,211,100,156,65,61,59,48,45,26,25,25,24,47,46,61,58,68,68,58,61,46,47,24,25,25,26,45,48, +59,61,65,158,98,211,2,138,120,254,148,170,24,23,49,46,61,56,68,67,57,60,47,46,26,24,25,24,47,48,59,56,69,66,58,59,47,48,24,25,170,254,146,0,2,0,65,0,25,4,144,4,137,0,13,0,105,0,0,1,54,53,52,39,38,35,34,7,6,21,20,23,22,23,6,7,54,51,50,23,22,21,20,7,6, +21,20,51,50,55,54,51,50,21,20,33,34,39,38,53,16,51,50,23,54,55,38,39,38,35,34,7,6,21,20,22,21,20,7,6,35,34,39,38,53,52,55,54,51,50,31,1,52,55,54,51,50,23,22,21,20,7,22,51,50,55,54,53,52,39,38,53,52,55,54,51,50,23,22,21,20,7,6,35,34,2,198,8,24,19,44,24, +19,15,35,60,90,17,37,76,70,101,48,36,251,124,85,94,14,41,44,51,255,0,166,151,161,212,83,66,63,13,82,187,56,60,68,51,33,35,22,29,16,26,20,12,94,76,95,85,40,61,33,35,63,62,40,41,13,49,70,61,34,37,17,34,17,25,46,52,34,17,116,78,97,53,3,140,38,36,52,33,27, +15,12,22,47,28,46,114,60,64,54,66,50,76,178,95,48,62,81,35,107,73,127,124,133,206,1,34,114,122,55,38,139,41,63,41,44,30,31,23,19,16,23,37,20,61,94,75,61,30,46,67,25,26,50,54,70,64,49,14,27,29,25,51,15,29,17,46,22,33,57,27,43,99,77,51,0,0,0,0,2,0,49,1, +51,4,160,3,198,0,7,0,78,0,0,1,6,7,6,7,54,55,54,1,32,53,52,55,38,39,38,7,22,7,6,7,22,51,50,55,22,21,20,35,34,39,35,53,51,54,55,54,55,38,39,38,39,38,53,52,51,6,21,20,23,22,23,50,23,22,23,38,53,52,55,54,51,50,19,22,51,50,53,52,39,38,53,52,51,50,21,20,7, +6,1,53,51,37,53,22,64,50,54,1,154,254,209,96,39,44,32,32,2,61,78,82,21,54,35,33,6,118,87,16,29,31,25,82,62,52,13,29,28,50,58,79,9,116,53,4,49,34,34,46,25,49,38,88,176,46,20,82,79,9,9,65,53,200,143,2,189,11,30,41,84,24,47,49,254,165,206,56,54,44,23,17, +1,70,65,83,12,58,35,24,40,61,139,58,116,65,48,2,15,14,15,11,14,57,83,24,28,31,68,32,20,16,16,39,65,35,53,31,24,254,215,125,49,24,15,14,22,49,66,141,79,57,0,0,1,0,240,255,155,3,225,5,130,0,32,0,0,5,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,51,21,34, +7,14,1,7,6,21,20,23,22,23,22,23,22,51,3,225,151,138,131,112,109,56,56,56,52,113,108,135,138,151,89,84,78,135,33,32,32,33,67,64,82,80,93,101,58,54,112,108,135,134,152,153,137,128,116,109,57,58,39,54,50,213,126,127,149,144,127,126,106,102,55,55,0,0,0,0, +1,0,240,255,155,3,225,5,130,0,34,0,0,23,48,53,50,55,54,55,54,55,54,53,52,39,46,1,39,38,35,48,53,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,240,93,80,82,64,67,33,32,32,33,135,78,84,89,151,138,135,108,113,52,56,56,56,109,112,131,138,101,39,54,55,102,106,126, +127,144,149,127,126,213,50,55,38,58,57,109,116,127,138,153,152,133,136,108,111,55,58,0,0,0,1,1,102,255,135,3,107,5,82,0,12,0,0,1,6,2,16,18,23,33,38,2,53,52,18,55,3,106,108,106,106,108,254,239,121,121,120,122,5,81,187,254,147,254,137,254,143,186,191,1, +113,182,181,1,112,191,0,0,0,0,1,1,110,255,135,3,99,5,36,0,15,0,0,1,48,33,22,18,21,20,7,6,7,33,54,55,54,16,2,1,110,1,9,119,117,59,59,118,254,247,105,52,51,102,5,36,186,254,156,176,176,179,179,185,181,178,178,1,108,1,99,0,0,0,1,1,67,255,125,3,142,5,85, +0,5,0,0,5,35,9,1,51,1,3,141,213,254,140,1,116,213,254,138,130,2,235,2,236,253,20,0,0,0,0,1,1,68,255,125,3,141,5,85,0,5,0,0,5,9,1,51,9,1,1,68,1,117,254,140,212,1,116,254,140,130,2,235,2,236,253,20,253,21,0,1,0,210,255,86,3,255,5,46,0,5,0,0,5,33,9,1,33, +1,3,254,254,182,254,31,1,225,1,74,254,22,169,2,235,2,236,253,20,0,0,1,0,210,255,86,3,255,5,46,0,5,0,0,23,9,1,33,9,1,211,1,234,254,22,1,74,1,225,254,31,169,2,235,2,236,253,20,253,21,0,1,0,205,255,65,4,4,5,209,0,5,0,0,5,33,9,1,33,1,4,3,254,109,254,94,1, +162,1,147,254,92,190,3,71,3,72,252,184,0,0,1,0,206,255,66,4,3,5,210,0,5,0,0,23,9,1,33,9,1,206,1,163,254,94,1,146,1,162,254,94,190,3,72,3,72,252,184,252,184,0,1,1,201,254,229,3,8,5,118,0,7,0,0,33,23,7,39,17,55,23,7,2,68,196,87,232,232,87,196,195,87,231, +4,194,231,87,195,0,0,0,1,1,201,254,235,3,8,5,124,0,7,0,0,1,39,55,23,17,7,39,55,2,141,196,87,232,232,87,196,4,98,195,87,231,251,62,231,87,195,0,1,1,25,254,184,3,184,5,94,0,36,0,0,5,21,35,34,38,61,1,52,38,43,1,53,51,50,54,61,1,52,54,59,1,21,35,34,6,29, +1,20,6,7,30,1,29,1,20,22,51,3,184,151,178,120,77,101,44,44,102,76,120,178,151,49,100,61,65,79,79,65,61,100,198,130,133,199,215,136,105,128,104,134,216,199,132,129,79,127,223,141,128,23,24,128,140,223,127,79,0,1,0,249,254,176,3,216,5,105,0,40,0,0,23,51, +50,54,61,1,52,54,55,38,39,38,61,1,52,38,43,1,53,51,50,23,22,29,1,20,23,22,59,1,21,35,34,6,29,1,20,7,6,43,1,250,53,110,67,70,86,85,36,35,67,110,53,165,194,66,66,42,41,112,47,47,111,84,66,66,194,165,204,80,128,226,142,129,25,22,65,65,143,225,129,80,130, +68,66,201,219,135,52,53,130,105,138,217,201,68,67,0,0,1,0,83,1,47,4,126,3,229,0,8,0,0,9,1,35,1,33,53,33,1,51,4,125,254,165,227,1,6,253,15,2,241,254,250,227,2,138,254,165,1,6,170,1,6,0,0,0,1,0,116,0,146,4,93,4,125,0,6,0,0,9,1,55,1,27,1,37,3,16,253,100, +148,2,94,186,61,253,164,1,138,2,93,149,253,100,1,14,253,164,62,0,1,0,83,1,162,4,126,4,18,0,6,0,0,1,5,53,5,3,9,1,3,47,253,37,2,219,48,1,126,254,130,2,168,35,170,35,1,5,254,201,254,201,0,0,1,0,116,0,193,4,93,4,171,0,6,0,0,9,1,39,1,45,1,3,3,102,253,162, +148,2,156,254,241,2,92,61,3,93,253,100,149,2,93,186,62,253,164,0,1,0,45,1,161,4,164,3,225,0,8,0,0,19,33,39,4,5,4,5,55,33,46,2,20,128,1,9,1,216,254,40,254,247,128,253,236,2,239,242,192,96,96,192,242,0,0,0,1,0,73,1,41,4,136,4,61,0,50,0,0,0,20,7,6,7,1,6, +7,6,34,38,39,38,39,38,53,52,55,54,63,1,33,34,46,1,39,38,52,55,62,2,51,33,39,38,39,38,53,52,55,54,55,62,1,50,23,22,23,1,22,4,136,7,9,12,254,212,12,18,17,39,33,13,14,7,7,7,8,13,139,253,96,19,33,27,8,6,6,8,27,33,19,2,160,139,13,8,7,7,7,14,13,33,39,17,18, +12,1,44,14,2,198,38,16,18,13,254,212,12,8,7,14,13,15,16,16,19,20,16,18,13,140,14,26,18,16,38,16,18,26,15,139,13,18,17,19,19,16,17,14,13,15,7,9,12,254,212,14,0,0,0,1,0,83,1,182,4,126,4,38,0,6,0,0,1,33,53,33,17,9,1,3,70,253,14,2,242,1,55,254,201,2,210, +56,1,27,254,201,254,201,0,1,0,45,1,120,4,164,4,20,0,6,0,0,1,33,53,33,53,9,1,3,86,252,216,3,40,1,77,254,179,2,114,168,250,254,178,254,178,0,0,4,0,54,1,117,4,155,4,6,0,3,0,7,0,11,0,18,0,0,1,35,17,51,3,35,17,51,3,35,17,51,1,33,17,33,53,9,1,1,233,180,180, +240,90,90,150,45,45,2,239,254,211,1,45,1,73,254,183,2,40,1,44,254,212,1,44,254,212,1,44,254,212,1,44,178,254,184,254,183,0,4,0,83,1,156,4,126,4,11,0,8,0,12,0,16,0,20,0,0,1,53,22,23,6,7,53,33,17,3,35,17,51,3,35,17,51,3,35,17,51,3,70,131,180,180,131,254, +227,57,171,171,228,85,85,142,42,42,3,169,98,218,93,94,218,98,1,171,254,85,1,171,254,85,1,171,254,85,1,171,0,1,0,83,1,132,4,126,3,244,0,6,0,0,1,33,17,33,53,9,1,3,70,253,14,2,242,1,55,254,201,2,46,1,28,169,254,201,254,201,0,2,0,96,1,116,4,113,4,24,0,2, +0,6,0,0,1,33,37,23,9,2,2,12,1,168,253,141,113,254,174,4,17,251,239,2,198,203,203,1,82,254,174,254,174,0,0,0,0,2,0,123,1,164,4,86,4,36,0,2,0,6,0,0,1,7,37,33,9,2,2,16,192,2,83,254,24,254,192,3,219,252,37,2,228,193,193,1,64,254,192,254,192,0,0,0,0,1,0,123, +1,31,4,86,4,189,0,3,0,0,1,3,9,1,1,116,249,3,219,252,37,2,238,1,206,254,50,254,50,0,0,0,0,1,0,54,1,140,4,155,4,61,0,22,0,0,19,17,20,23,22,23,22,23,22,51,33,53,9,1,53,33,34,39,38,39,38,39,38,54,14,13,27,26,32,32,36,2,104,1,73,254,183,253,152,36,32,32,26, +27,13,14,2,213,1,104,36,32,32,27,25,15,13,149,254,183,254,183,149,13,15,25,27,32,32,0,0,1,0,54,1,139,4,155,4,60,0,22,0,0,19,52,55,54,55,54,55,54,51,33,53,9,1,53,33,34,7,6,7,6,7,6,21,54,14,13,27,26,32,32,36,2,104,1,73,254,183,253,152,36,32,32,26,27,13, +14,2,243,36,32,32,27,25,15,13,149,254,183,254,183,149,13,15,25,27,32,32,36,0,0,0,1,1,79,1,6,3,130,4,224,0,6,0,0,1,33,17,33,17,9,1,2,101,254,235,1,21,1,28,254,228,2,18,1,194,1,12,254,19,254,19,0,0,0,0,1,0,54,1,110,4,155,4,0,0,8,0,0,1,53,22,5,4,7,53,33, +17,2,226,108,1,77,254,179,108,253,84,3,137,119,230,99,99,230,119,1,164,0,0,2,0,101,1,107,4,108,4,33,0,8,0,15,0,0,1,53,33,17,33,53,51,9,1,39,21,9,1,21,33,21,2,95,254,6,1,250,178,1,91,254,165,121,1,34,254,222,254,6,1,107,169,1,100,169,254,165,254,165,226, +169,1,34,1,34,169,242,0,2,0,101,1,47,4,108,3,229,0,8,0,15,0,0,1,53,33,17,33,53,51,9,1,39,21,9,1,21,33,21,2,95,254,6,1,250,178,1,91,254,165,15,1,34,254,222,254,7,1,47,169,1,100,169,254,165,254,165,226,169,1,34,1,34,169,242,0,2,0,53,0,183,4,156,3,252,0, +11,0,18,0,0,27,1,33,55,51,19,21,1,35,53,55,33,37,7,1,3,7,33,7,54,205,2,85,99,71,153,253,249,106,15,253,253,2,182,98,1,202,122,98,253,170,140,1,239,1,100,169,254,147,143,254,184,142,27,199,169,1,34,1,34,169,242,0,0,0,2,0,97,0,214,4,112,3,171,0,11,0,18, +0,0,19,53,33,39,53,51,1,21,3,35,39,33,1,33,23,33,23,55,37,97,1,220,15,99,1,223,142,65,91,253,216,1,196,253,216,129,2,40,90,113,254,90,2,157,123,23,123,254,228,123,254,196,146,1,3,210,146,251,251,0,0,2,0,125,0,219,4,84,4,77,0,10,0,17,0,0,37,39,33,39,17, +33,53,51,1,23,1,3,21,9,1,21,33,17,2,147,59,254,113,75,1,202,82,1,110,75,254,146,97,1,50,254,206,254,54,219,119,150,1,238,119,254,146,150,254,146,1,73,119,1,50,1,50,119,254,138,0,2,0,84,0,130,4,125,4,62,0,10,0,17,0,0,1,51,1,7,1,35,53,33,17,55,33,23,33, +17,33,21,9,1,2,150,90,1,140,81,254,116,90,254,16,81,1,176,48,254,16,1,240,1,76,254,180,4,62,254,115,162,254,115,129,2,24,163,228,254,106,129,1,76,1,75,0,2,0,50,1,78,4,159,4,117,0,12,0,20,0,0,19,39,33,53,51,1,23,1,35,39,53,33,39,55,7,33,21,9,1,21,33,163, +112,2,133,83,1,110,37,254,146,82,38,253,160,37,181,85,2,97,1,50,254,206,253,159,3,7,247,119,254,146,75,254,146,74,44,76,247,187,119,1,50,1,50,119,0,0,0,2,0,41,0,253,4,168,4,49,0,12,0,20,0,0,19,39,55,33,53,55,51,1,7,1,35,53,33,55,7,33,21,9,1,21,33,156, +114,38,2,106,38,83,1,116,38,254,140,83,253,112,184,87,2,108,1,54,254,202,253,148,2,113,251,77,44,76,254,140,76,254,140,121,251,190,121,1,55,1,55,121,0,0,0,1,0,145,0,189,4,64,4,172,0,33,0,0,19,54,55,54,55,54,51,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35, +34,39,38,39,38,39,33,21,9,1,21,145,32,54,73,89,90,103,98,94,85,77,73,37,38,38,34,76,70,92,90,102,99,94,85,77,51,33,1,231,1,116,254,140,3,167,58,54,73,38,38,38,35,76,72,90,90,104,99,92,85,77,72,39,38,38,35,76,50,60,129,1,116,1,116,128,0,0,0,0,9,0,88,1, +78,4,121,3,22,0,3,0,7,0,11,0,15,0,30,0,34,0,38,0,42,0,46,0,0,1,7,51,55,35,7,51,55,35,7,51,55,35,7,51,55,35,53,39,33,23,33,53,22,23,6,7,53,33,7,33,1,51,39,35,23,51,39,35,23,51,39,35,23,51,39,35,2,8,114,43,113,127,114,42,114,128,114,43,114,128,114,43,114, +86,133,1,128,133,1,22,123,139,139,123,254,234,133,254,128,1,176,42,113,43,29,42,114,42,28,43,114,43,29,43,114,43,2,21,171,171,171,171,171,171,171,171,57,199,199,198,134,92,93,134,198,199,1,0,171,171,171,171,171,171,171,0,3,0,116,0,185,4,93,4,162,0,12, +0,16,0,20,0,0,1,55,6,21,20,23,38,35,34,7,55,39,55,9,1,35,1,37,53,1,21,3,178,142,6,35,116,133,54,57,143,207,46,254,119,1,90,230,254,166,1,21,1,89,1,147,143,57,54,133,116,34,6,143,207,46,1,42,254,168,1,88,47,230,254,167,229,0,0,0,0,3,0,83,1,209,4,126,3, +107,0,8,0,12,0,16,0,0,1,53,22,23,6,7,53,33,53,5,33,7,33,55,39,33,23,3,141,110,130,130,110,255,0,254,85,1,170,142,254,86,142,142,1,170,142,2,186,177,134,71,71,134,177,56,58,142,200,143,143,0,0,0,0,3,0,117,0,129,4,92,4,106,0,12,0,16,0,20,0,0,1,39,22,51, +50,55,6,21,20,23,39,7,39,9,1,21,1,3,35,1,51,3,131,142,57,53,133,116,34,5,142,207,46,254,214,1,89,254,167,47,230,1,89,230,3,191,143,6,34,117,132,54,57,143,207,46,254,120,1,88,230,254,168,1,21,1,88,0,0,0,0,1,0,78,0,185,4,131,4,238,0,50,0,0,37,38,35,34, +7,54,55,54,55,1,38,39,38,34,7,6,7,1,54,55,54,51,50,23,22,23,38,39,38,53,52,55,54,55,1,6,7,6,21,20,23,22,23,1,54,55,54,55,6,21,20,4,130,125,144,58,60,63,77,35,21,254,246,25,31,33,68,34,32,24,254,141,31,36,40,42,38,42,38,29,29,15,17,17,15,29,1,115,28,9, +12,12,13,24,1,10,3,14,32,63,6,186,36,6,62,34,14,2,1,9,26,12,13,13,13,25,1,115,32,14,16,16,15,31,31,37,42,38,42,40,38,30,254,140,29,27,34,33,35,33,30,26,254,247,20,34,79,62,62,59,142,0,0,0,0,1,0,42,1,137,4,167,3,69,0,47,0,0,1,6,7,52,55,54,55,33,34,7,6, +7,6,7,6,21,33,52,55,54,55,54,55,54,51,34,39,38,39,38,39,38,53,33,20,23,22,23,22,23,22,51,33,38,39,38,53,22,4,166,140,118,28,12,11,254,184,31,27,28,22,21,12,12,254,53,13,15,26,24,36,32,37,37,32,36,24,26,15,13,1,203,12,12,21,22,28,27,31,1,72,11,12,28,118, +2,103,77,144,77,69,30,14,11,12,22,20,30,27,31,37,33,35,25,24,16,14,14,16,24,26,34,33,37,31,27,30,20,22,12,11,14,30,69,77,144,0,0,0,1,0,117,0,175,4,92,4,151,0,50,0,0,1,6,21,20,23,38,39,38,39,7,6,7,6,21,20,23,22,23,1,38,39,38,53,52,55,54,55,6,7,6,35,34, +39,38,39,1,22,23,22,50,55,54,63,1,38,39,38,39,22,51,50,4,92,34,6,58,30,13,4,246,25,10,11,11,12,23,254,168,28,14,15,15,14,28,28,35,39,36,39,36,35,28,1,89,22,30,31,64,31,28,24,246,20,31,73,58,56,54,134,4,151,115,133,54,58,58,73,32,18,246,27,25,31,31,31, +32,29,23,254,167,27,35,38,39,35,39,34,29,29,13,15,15,14,28,1,88,22,13,12,12,12,23,247,2,13,31,58,6,0,0,0,3,0,53,1,42,4,156,3,236,0,22,0,43,0,66,0,0,1,54,55,6,7,6,7,6,7,6,34,39,38,39,38,39,38,53,52,55,54,55,54,36,52,55,54,55,54,55,54,50,23,4,5,4,7,6,34, +39,38,39,38,39,37,38,39,38,39,38,53,52,55,54,55,54,55,54,50,23,22,23,22,23,22,23,36,3,3,184,224,170,91,9,16,17,20,19,47,19,21,16,16,9,8,8,9,16,16,253,72,11,13,20,22,27,26,61,27,1,8,2,141,253,97,246,27,61,26,31,18,22,11,2,194,21,16,16,9,8,8,9,16,16,21, +19,47,19,20,17,13,12,90,171,254,239,2,4,73,61,88,194,22,15,15,10,8,8,10,15,15,22,20,24,22,20,22,15,16,113,62,26,30,19,21,12,12,11,100,40,42,99,10,11,14,19,24,25,193,9,15,16,21,21,22,23,21,21,15,16,9,8,8,9,16,12,24,194,88,74,0,0,0,2,0,29,1,110,4,180,3, +176,0,26,0,46,0,0,19,54,55,54,55,54,55,54,51,50,23,22,23,22,5,4,7,14,1,35,34,39,38,39,38,39,38,37,38,39,38,53,52,55,54,55,22,23,6,7,38,39,38,53,52,55,54,29,53,24,26,16,32,32,35,38,43,42,49,41,132,1,70,254,186,132,45,89,41,41,32,46,18,23,19,23,3,69,30, +15,16,16,15,30,79,205,205,79,30,15,16,16,15,2,143,31,47,51,16,29,15,15,15,18,26,83,62,62,83,28,31,15,24,20,29,38,47,31,32,35,36,41,41,37,35,31,195,93,93,195,31,35,37,41,41,36,35,0,0,0,0,1,0,38,1,190,4,171,3,166,0,101,0,0,0,20,6,15,1,6,7,6,34,39,38,39, +46,1,53,52,63,1,54,53,52,39,38,39,38,39,38,43,1,34,7,6,7,6,15,1,6,7,6,7,6,35,33,34,46,2,52,63,1,54,52,47,1,38,52,54,55,54,55,54,51,33,50,23,22,23,22,31,1,22,23,22,23,22,59,1,50,55,54,55,54,55,54,53,52,47,1,38,53,52,54,55,54,55,54,50,23,22,31,1,22,4,171, +5,5,195,3,7,6,13,6,5,5,5,5,2,22,3,3,2,5,4,6,7,6,229,6,6,6,5,4,3,73,4,3,4,7,5,6,254,14,6,11,10,5,2,93,3,3,93,2,5,5,5,5,6,6,1,242,6,5,7,4,3,4,73,3,4,5,6,6,6,229,6,7,6,4,5,2,3,3,22,2,5,5,5,5,6,13,6,7,3,195,5,2,185,14,12,5,195,3,4,2,2,3,4,5,12,7,3,9,81,9, +4,5,6,6,5,4,3,3,2,4,4,4,6,146,9,2,4,3,3,5,10,11,15,5,185,5,16,5,185,5,15,11,5,4,3,3,3,2,5,2,9,146,6,4,4,4,2,3,3,4,5,6,6,5,4,9,81,9,3,7,12,5,4,3,2,2,4,3,195,5,0,0,0,0,1,0,37,1,101,4,171,3,241,0,103,0,0,0,20,7,6,7,1,6,7,6,34,39,38,39,46,1,53,52,63,1,54, +53,52,39,38,39,38,39,38,43,1,34,7,6,7,6,15,1,6,7,6,7,6,35,33,34,46,2,52,63,1,54,52,47,1,38,52,54,55,54,55,54,51,33,50,23,22,23,22,31,1,22,23,22,23,22,59,1,50,55,54,55,54,55,54,53,52,47,1,38,53,52,54,55,54,55,54,50,23,22,23,1,22,23,4,171,2,3,5,254,187, +4,6,6,13,6,5,5,5,5,2,71,3,3,2,5,4,7,6,6,75,6,6,6,4,5,3,97,4,3,5,6,5,7,253,231,7,11,10,5,3,117,2,2,126,2,5,5,5,5,6,6,2,26,7,5,7,4,3,4,105,3,5,4,6,6,6,75,6,6,7,4,5,2,3,3,71,2,5,5,5,5,6,13,6,6,4,1,69,5,3,2,178,14,6,6,5,254,220,4,3,3,3,3,4,5,11,7,6,7,178, +6,7,5,6,7,4,4,3,3,2,4,4,4,6,195,8,3,4,3,3,5,10,11,15,5,234,5,16,5,250,5,15,11,5,4,3,3,3,2,5,2,9,211,6,4,4,4,2,3,3,4,4,7,6,5,7,6,178,7,6,7,11,5,4,3,3,3,3,4,254,220,5,6,0,0,3,0,50,1,12,4,159,3,178,0,19,0,31,0,43,0,0,1,6,7,6,7,35,55,54,55,54,55,38,39,38, +47,1,51,22,23,22,1,35,54,55,54,55,33,53,33,6,7,6,3,22,23,22,23,33,53,33,38,39,38,39,4,159,103,63,106,55,82,8,61,121,29,54,54,29,121,61,8,82,54,107,63,254,86,79,14,18,23,32,253,156,2,241,83,43,13,10,10,13,43,83,253,15,2,100,32,23,18,14,2,95,56,61,101, +121,17,139,117,27,39,38,28,117,138,17,116,106,60,254,117,44,42,52,52,71,101,101,29,2,135,29,29,101,101,71,51,53,42,43,0,0,255,255,0,88,0,0,4,121,5,4,16,6,8,173,0,0,0,1,1,56,254,178,3,154,6,38,0,25,0,0,1,42,1,39,36,3,38,0,39,38,35,34,7,39,54,55,54,21, +20,0,7,6,5,22,54,55,3,154,9,104,55,254,72,2,1,1,109,4,3,94,58,45,136,51,213,222,254,176,7,12,1,28,82,69,20,254,178,11,83,1,82,174,3,245,81,79,137,49,216,1,1,204,161,252,76,143,220,72,21,1,2,0,0,1,1,55,254,178,3,153,6,38,0,25,0,0,1,53,30,1,55,36,39,38, +0,53,52,23,22,23,7,38,35,34,7,6,0,7,2,5,6,34,1,55,20,69,82,1,28,12,7,254,176,222,213,51,136,45,58,94,3,4,1,109,1,2,254,72,55,104,254,178,143,2,1,21,72,220,143,3,180,161,204,1,1,216,49,137,79,81,252,11,174,254,174,83,11,0,0,2,0,28,1,103,4,181,3,162,0, +13,0,21,0,0,1,7,33,6,7,6,34,38,52,54,50,23,22,23,4,22,50,54,52,38,34,6,4,181,1,253,151,19,49,91,235,165,162,242,83,52,19,254,102,79,115,80,79,116,79,2,219,168,68,47,89,167,242,162,82,51,66,142,80,81,113,79,79,0,0,3,0,117,254,35,4,92,6,117,0,3,0,6,0,9, +0,0,9,5,33,9,1,33,2,104,1,244,254,12,254,13,1,243,254,152,2,209,254,151,1,105,253,47,6,117,251,219,251,211,4,45,3,49,253,8,252,142,3,0,0,2,1,41,254,242,3,169,6,20,0,3,0,11,0,0,1,17,51,17,37,33,21,35,17,51,21,33,1,141,200,254,212,2,128,240,240,253,128, +5,176,249,166,6,90,100,100,249,166,100,0,0,0,2,1,40,254,242,3,168,6,20,0,3,0,11,0,0,1,35,17,51,19,17,33,53,51,17,35,53,3,68,200,200,100,253,128,240,240,5,176,249,166,6,190,248,222,100,6,90,100,0,0,0,0,1,1,134,254,242,3,75,6,18,0,5,0,0,9,1,51,9,1,35,1, +135,1,25,170,254,231,1,25,170,2,130,3,144,252,112,252,112,0,0,0,1,1,134,254,242,3,75,6,18,0,5,0,0,9,1,35,9,1,51,3,74,254,231,170,1,25,254,231,170,2,130,252,112,3,144,3,144,0,0,255,255,0,190,254,242,4,9,6,18,16,39,11,131,0,190,0,0,16,7,11,131,255,56,0, +0,0,0,255,255,0,190,254,242,4,19,6,18,16,39,11,132,0,200,0,0,16,7,11,132,255,56,0,0,0,0,0,1,255,156,0,229,5,53,3,125,0,9,0,0,3,1,23,7,33,21,33,23,7,1,100,1,35,90,160,4,188,251,68,160,90,254,221,2,90,1,35,90,160,164,160,90,1,35,0,1,255,156,0,229,5,53, +3,125,0,9,0,0,9,1,39,55,33,53,33,39,55,1,5,53,254,221,90,160,251,68,4,188,160,90,1,35,2,8,254,221,90,160,164,160,90,254,221,0,0,0,0,1,255,156,0,229,5,53,3,125,0,15,0,0,9,1,39,55,33,23,7,1,53,1,23,7,33,39,55,1,5,53,254,221,90,160,252,33,160,90,254,221, +1,35,90,160,3,223,160,90,1,35,2,8,254,221,90,160,160,90,1,35,82,1,35,90,160,160,90,254,221,0,0,2,1,44,254,242,3,165,6,18,0,6,0,13,0,0,1,36,0,17,16,0,37,7,6,2,21,20,18,23,3,165,254,176,254,215,1,33,1,88,100,145,213,213,145,254,242,81,2,19,1,45,1,44,2, +16,83,181,39,254,72,251,252,254,72,40,0,0,0,2,1,44,254,242,3,165,6,18,0,6,0,13,0,0,1,4,0,17,16,0,5,55,54,18,53,52,2,39,1,44,1,80,1,41,254,223,254,168,100,145,213,213,145,6,18,81,253,237,254,211,254,212,253,240,83,181,39,1,184,251,252,1,184,40,0,0,0,1, +1,144,254,190,3,215,6,72,0,7,0,0,9,1,17,1,23,1,17,1,3,114,254,30,1,226,101,254,233,1,23,254,190,1,225,3,200,1,225,101,254,234,251,108,254,234,0,1,0,250,254,190,3,65,6,72,0,7,0,0,9,1,17,1,39,1,17,1,1,95,1,226,254,30,101,1,23,254,233,6,72,254,31,252,56, +254,31,101,1,22,4,148,1,22,0,1,0,117,254,35,4,92,6,117,0,3,0,0,9,3,2,104,1,244,254,12,254,13,6,117,251,219,251,211,4,45,0,1,0,88,0,113,4,121,4,147,0,19,0,0,1,17,51,17,51,21,35,17,35,17,35,17,35,17,35,53,51,17,51,17,2,220,168,245,245,168,232,168,244,244, +168,2,215,1,188,254,68,170,254,68,1,188,254,68,1,188,170,1,188,254,68,0,0,0,0,1,0,88,0,113,4,121,4,147,0,27,0,0,19,17,51,17,51,17,51,17,51,17,51,17,51,21,35,17,35,17,35,17,35,17,35,17,35,17,35,53,202,168,162,168,162,168,115,115,168,162,168,162,168,114, +2,215,1,188,254,68,1,188,254,68,1,188,254,68,170,254,68,1,188,254,68,1,188,254,68,1,188,170,0,3,0,80,254,47,4,129,6,11,0,3,0,11,0,19,0,0,1,51,17,35,19,32,17,16,33,32,17,16,37,32,17,16,33,32,17,16,1,233,252,252,127,254,116,1,140,1,141,254,115,2,25,253, +231,253,232,2,169,254,207,4,7,252,155,252,161,3,95,3,101,140,252,15,252,21,3,235,3,241,255,255,0,150,0,174,4,59,4,84,16,6,0,153,0,0,255,255,0,88,1,241,4,121,4,132,16,38,8,75,0,0,16,7,8,182,0,2,1,36,255,255,0,88,0,134,4,121,4,132,16,38,8,75,0,0,16,39, +8,182,0,242,1,36,16,7,8,182,255,17,254,87,0,1,0,84,1,133,4,125,3,243,0,6,0,0,1,33,17,33,21,9,1,1,139,2,242,253,14,254,201,1,55,3,74,254,228,169,1,55,1,55,0,1,1,49,0,167,3,160,4,209,0,6,0,0,1,17,33,17,35,9,1,2,247,254,227,169,1,55,1,56,3,153,253,14,2, +242,1,56,254,200,0,1,1,49,0,167,3,160,4,209,0,6,0,0,1,17,33,17,51,9,1,1,218,1,29,169,254,201,254,200,1,223,2,242,253,14,254,200,1,56,0,1,0,139,0,223,3,225,4,53,0,6,0,0,9,1,39,1,39,33,17,3,106,253,234,201,2,22,120,1,184,2,244,253,235,201,2,21,120,254, +71,0,0,0,0,1,0,240,0,223,4,70,4,53,0,6,0,0,9,1,7,1,7,17,33,2,48,2,22,201,253,234,119,1,184,3,189,253,235,201,2,21,120,1,185,0,0,0,0,1,0,240,0,223,4,70,4,53,0,6,0,0,9,1,55,1,55,17,33,3,5,253,235,201,2,21,120,254,71,1,86,2,22,201,253,234,120,254,72,0,0, +0,0,1,0,139,0,223,3,225,4,53,0,6,0,0,9,1,23,1,23,33,17,1,3,2,21,201,253,235,120,254,71,2,31,2,22,201,253,234,119,1,184,0,0,0,0,1,0,84,1,133,4,125,3,243,0,9,0,0,1,33,53,9,1,53,33,21,9,1,1,139,1,187,1,55,254,201,254,69,254,201,1,55,3,74,169,254,201,254, +201,169,169,1,55,1,55,0,0,1,1,49,0,167,3,160,4,209,0,9,0,0,1,17,35,9,1,35,17,51,9,1,1,218,169,1,56,1,55,169,169,254,201,254,200,1,223,1,186,1,56,254,200,254,70,254,200,1,56,0,0,2,0,6,255,177,4,203,4,119,0,3,0,7,0,0,55,33,17,33,3,17,33,17,120,3,225,252, +31,114,4,197,36,1,240,253,158,4,196,251,60,0,0,0,0,2,0,6,255,177,4,203,4,119,0,3,0,7,0,0,19,33,17,33,3,17,33,17,120,3,225,252,31,114,4,197,2,20,1,240,251,174,4,196,251,60,0,0,0,2,0,6,255,177,4,203,4,119,0,2,0,6,0,0,55,33,1,3,17,33,17,120,3,225,252,31, +114,4,197,36,3,224,251,174,4,196,251,60,0,2,0,6,255,177,4,203,4,119,0,2,0,6,0,0,37,17,33,3,17,33,17,4,89,252,31,114,4,197,36,3,224,251,174,4,196,251,60,0,0,2,0,6,255,177,4,203,4,119,0,2,0,6,0,0,37,9,5,2,104,1,203,254,53,253,158,2,98,2,99,253,157,74,1, +202,1,202,254,54,2,98,253,158,253,158,0,0,0,2,0,6,255,177,4,203,4,119,0,2,0,6,0,0,19,1,17,9,3,158,1,202,253,158,2,98,2,99,253,157,2,20,254,54,3,148,254,54,2,98,253,158,253,158,0,0,0,2,0,6,255,177,4,203,4,119,0,2,0,6,0,0,19,9,1,33,9,2,158,1,202,1,203, +251,211,2,98,2,99,253,157,2,20,254,54,1,202,2,98,253,158,253,158,0,0,2,0,6,255,177,4,203,4,119,0,2,0,6,0,0,19,33,9,4,158,3,149,254,53,253,158,2,98,2,99,253,157,2,20,1,202,254,54,2,98,253,158,253,158,0,0,0,0,12,0,6,255,177,4,203,4,119,0,5,0,9,0,13,0,17, +0,21,0,27,0,31,0,35,0,41,0,45,0,49,0,55,0,0,37,21,35,53,51,53,19,21,35,53,19,21,35,53,3,21,35,53,35,21,35,53,39,21,51,21,35,53,19,21,35,53,19,21,35,53,1,21,35,53,35,53,35,21,35,53,35,21,35,53,35,21,35,21,35,53,4,203,205,90,115,115,115,115,244,174,154, +180,240,86,200,114,114,114,114,4,197,115,90,154,174,154,180,154,86,114,126,204,114,90,1,72,174,174,1,78,179,179,253,16,114,114,114,114,90,90,114,204,1,72,174,174,1,78,179,179,1,98,200,86,114,114,114,114,114,114,86,200,0,2,0,143,254,76,4,209,5,213,0,30, +0,39,0,0,23,17,33,50,4,21,20,6,7,22,23,22,23,19,35,3,46,1,43,1,17,20,23,22,59,1,21,35,34,39,38,19,17,51,50,54,53,52,38,35,143,1,160,246,1,6,161,146,78,55,54,83,203,217,178,77,123,99,193,44,45,90,185,223,165,90,89,203,221,145,142,151,144,30,5,243,222, +210,148,187,21,20,55,55,167,254,104,1,121,161,93,253,107,126,62,62,156,106,105,6,16,253,238,130,134,129,137,0,0,2,0,106,255,227,4,82,5,240,0,19,0,34,0,0,1,53,51,17,35,53,6,7,6,35,34,39,38,17,16,0,51,50,23,22,0,16,23,22,51,50,55,54,17,16,39,38,35,34,7, +3,154,184,184,51,85,86,110,225,129,130,1,4,224,112,86,84,253,213,77,76,149,148,78,77,77,78,148,149,76,5,65,148,250,43,193,108,57,57,207,209,1,108,1,103,1,154,45,44,254,128,253,165,155,154,156,153,1,46,1,46,153,155,154,0,0,1,0,86,254,86,4,121,5,213,0, +22,0,0,9,1,35,1,17,35,17,33,9,1,33,17,20,7,6,43,1,53,51,50,55,54,53,3,190,254,246,153,254,245,186,1,14,1,2,1,4,1,15,89,90,165,205,183,90,45,44,5,39,252,237,3,19,250,217,5,213,253,8,2,248,250,23,195,105,106,156,62,62,146,0,2,0,37,0,0,4,172,5,213,0,2,0, +10,0,0,37,19,33,1,35,1,51,19,33,19,51,2,105,213,254,86,1,79,245,254,55,209,110,2,11,108,209,178,2,252,252,82,5,213,254,123,1,133,0,0,0,2,0,106,255,227,4,82,5,240,0,19,0,34,0,0,37,21,35,17,51,21,54,55,54,51,50,23,22,17,16,0,35,34,39,38,0,16,39,38,35,34, +7,6,17,16,23,22,51,50,55,1,34,184,184,51,85,86,110,225,129,130,254,252,224,112,86,84,2,43,77,76,149,148,78,77,77,78,148,149,76,146,148,5,213,193,108,57,57,207,209,254,148,254,153,254,102,45,44,1,128,2,91,155,154,156,153,254,211,254,209,153,155,154,0, +0,0,1,0,137,0,0,4,72,5,213,0,7,0,0,19,51,17,33,21,33,17,35,137,203,2,244,253,12,203,5,213,253,156,170,253,57,0,1,0,195,0,0,4,26,4,96,0,7,0,0,1,17,35,17,51,17,33,21,1,123,184,184,2,159,2,3,253,253,4,96,254,57,150,0,0,0,0,2,0,76,255,231,4,133,4,104,0,10, +0,39,0,0,1,34,21,17,50,55,54,53,52,39,38,39,50,23,22,17,16,7,6,35,7,34,39,38,17,16,55,54,55,21,6,7,6,21,20,23,22,51,17,16,3,5,65,92,86,77,77,71,42,138,119,127,127,129,193,183,199,124,126,126,104,154,65,49,76,76,78,101,3,203,145,253,82,104,93,223,221, +99,91,157,132,141,254,217,254,230,150,152,1,153,155,1,20,1,44,132,109,28,163,26,75,115,190,216,101,103,2,175,1,46,0,0,0,1,0,152,255,229,3,177,6,20,0,25,0,0,33,35,53,14,1,35,34,38,39,53,30,1,51,50,54,53,17,52,38,43,1,53,51,50,22,21,3,177,185,46,191,131, +68,118,54,59,122,73,172,182,77,99,209,221,179,170,219,119,127,34,36,188,46,42,216,204,2,144,103,81,153,174,184,0,0,0,0,3,0,137,255,227,4,72,4,123,0,7,0,15,0,30,0,0,0,34,6,20,22,50,54,52,0,32,18,16,2,32,2,16,1,16,32,17,20,23,54,55,54,51,50,23,22,23,54, +2,173,134,94,92,135,96,254,115,1,210,247,246,254,45,246,2,252,253,199,6,22,33,92,133,135,91,30,21,6,1,192,94,136,91,93,133,3,26,254,210,253,195,254,211,1,45,2,61,254,226,1,176,254,80,64,55,39,34,93,95,30,36,53,0,0,0,255,255,1,230,255,17,2,235,3,104,18, +7,2,88,0,0,253,100,0,0,0,1,1,8,2,156,3,201,5,224,0,6,0,0,1,19,51,1,35,1,51,2,104,221,132,254,237,155,254,237,132,2,251,2,229,252,188,3,68,0,0,1,0,139,254,16,4,143,5,240,0,56,0,0,1,21,46,1,35,34,6,21,20,22,31,1,30,1,21,20,7,6,7,23,22,59,1,21,35,34,46, +3,47,1,46,1,39,38,39,53,30,1,51,50,54,53,52,38,47,1,38,39,38,53,52,36,51,50,22,3,244,92,185,94,143,166,109,149,106,210,192,132,106,183,130,186,150,24,51,33,50,95,80,102,45,222,20,69,29,102,111,115,205,104,153,170,117,145,108,209,93,94,1,13,223,86,190, +5,162,205,59,60,133,113,99,104,35,24,49,210,181,213,112,90,18,137,164,170,3,18,34,68,48,236,22,55,6,20,47,215,73,68,137,123,112,118,32,25,48,94,95,160,200,241,39,0,0,0,0,1,0,156,254,16,4,146,5,213,0,26,0,0,51,53,1,33,53,33,21,1,22,31,1,30,3,59,1,21,35, +34,46,2,47,1,38,35,156,2,247,253,31,3,201,252,244,102,97,212,45,66,81,79,40,81,114,32,76,99,117,57,253,66,95,154,4,145,170,154,251,111,14,94,205,44,57,55,27,170,17,38,80,55,243,63,0,0,0,3,0,193,254,112,3,221,4,96,0,23,0,27,0,37,0,0,1,51,17,54,55,54,55, +21,6,7,6,35,34,39,38,53,52,55,54,63,1,62,1,53,19,21,35,53,19,17,7,6,7,6,21,20,23,22,2,37,190,31,32,89,98,94,96,95,104,186,111,110,34,33,94,88,69,38,197,203,6,45,62,23,24,66,37,2,207,252,83,8,12,35,68,188,57,28,28,96,96,161,76,65,66,92,86,66,84,61,2,59, +254,254,250,190,1,174,45,59,44,44,49,89,55,31,255,255,0,88,0,134,4,121,3,18,16,38,8,75,0,0,16,7,8,182,0,1,254,87,0,1,1,207,3,58,3,119,6,20,0,5,0,0,1,33,21,35,17,35,1,207,1,168,240,184,6,20,143,253,181,0,0,1,1,90,3,58,3,2,6,20,0,5,0,0,1,35,53,33,17,35, +2,74,240,1,168,184,5,133,143,253,38,0,0,1,1,207,254,242,3,119,1,204,0,5,0,0,5,51,21,33,17,51,2,135,240,254,88,184,127,143,2,218,0,0,0,1,1,90,254,242,3,2,1,204,0,5,0,0,1,33,53,51,17,51,3,2,254,88,240,184,254,242,143,2,75,0,255,255,0,218,0,0,3,247,5,240, +16,6,4,86,0,0,0,2,1,44,0,0,3,165,5,88,0,3,0,7,0,0,1,51,21,35,1,17,51,17,1,44,170,170,1,241,136,5,88,136,251,48,5,88,250,168,0,2,1,44,0,0,3,165,5,88,0,3,0,7,0,0,1,51,21,35,1,17,51,17,1,44,170,170,1,241,136,4,36,136,252,100,5,88,250,168,0,2,1,44,0,0,3, +165,5,88,0,3,0,7,0,0,1,51,21,35,1,17,51,17,1,44,170,170,1,241,136,2,240,136,253,152,5,88,250,168,0,2,1,44,0,0,3,165,5,88,0,3,0,7,0,0,1,51,21,35,1,17,51,17,1,44,170,170,1,241,136,1,188,136,254,204,5,88,250,168,0,2,1,44,0,0,3,165,5,88,0,3,0,7,0,0,37,51, +21,35,1,51,17,35,1,44,170,170,1,241,136,136,136,136,5,88,250,168,0,0,0,2,1,44,0,0,3,165,5,88,0,3,0,7,0,0,1,51,21,35,1,35,17,51,2,251,170,170,254,185,136,136,5,88,136,251,48,5,88,0,0,2,1,44,0,0,3,165,5,88,0,3,0,7,0,0,1,51,21,35,1,35,17,51,2,251,170,170, +254,185,136,136,4,36,136,252,100,5,88,0,0,2,1,44,0,0,3,165,5,88,0,3,0,7,0,0,1,51,21,35,1,35,17,51,2,251,170,170,254,185,136,136,2,240,136,253,152,5,88,0,0,2,1,44,0,0,3,165,5,88,0,3,0,7,0,0,1,51,21,35,1,35,17,51,2,251,170,170,254,185,136,136,1,188,136, +254,204,5,88,0,0,2,1,44,0,0,3,165,5,88,0,3,0,7,0,0,37,51,21,35,33,35,17,51,2,251,170,170,254,185,136,136,136,136,5,88,0,1,1,44,0,0,3,165,5,88,0,5,0,0,33,35,17,33,21,33,1,180,136,2,121,254,15,5,88,136,0,0,0,1,1,44,0,0,3,165,5,88,0,7,0,0,33,35,17,51,17, +33,21,33,1,180,136,136,1,241,254,15,5,88,254,204,136,0,0,1,1,44,0,0,3,165,5,88,0,7,0,0,33,35,17,51,17,33,21,33,1,180,136,136,1,241,254,15,5,88,253,152,136,0,0,1,1,44,0,0,3,165,5,88,0,7,0,0,33,35,17,51,17,33,21,33,1,180,136,136,1,241,254,15,5,88,252,100, +136,0,0,1,1,44,0,0,3,165,5,88,0,5,0,0,37,33,21,33,17,51,1,180,1,241,253,135,136,136,136,5,88,0,0,1,1,84,2,156,3,124,5,228,0,9,0,0,1,51,23,7,39,17,35,17,7,39,2,76,58,246,76,146,106,148,76,5,228,221,67,131,253,85,2,171,131,67,0,1,1,84,2,152,3,124,5,224, +0,9,0,0,1,35,39,55,23,17,51,17,55,23,2,134,58,248,76,148,106,146,76,2,152,221,67,131,2,171,253,85,131,67,0,2,2,40,2,156,2,168,5,224,0,3,0,9,0,0,1,51,21,35,17,51,17,7,35,39,2,40,128,128,128,12,102,14,3,42,142,3,68,254,145,200,200,0,0,2,2,40,2,156,2,168, +5,224,0,3,0,9,0,0,1,35,53,51,17,35,17,55,51,23,2,168,128,128,128,12,102,14,5,82,142,252,188,1,111,200,200,0,255,255,2,40,0,0,2,168,3,68,16,7,11,206,0,0,253,100,0,0,0,1,1,65,0,0,3,183,5,212,0,16,0,0,33,53,32,2,33,53,32,2,33,53,32,19,22,7,22,19,18,1,135, +1,124,20,254,132,1,124,30,254,112,2,79,14,9,174,184,6,10,163,2,39,163,1,197,162,254,140,229,99,109,254,251,254,90,0,0,1,1,110,0,0,3,158,4,96,0,16,0,0,33,53,32,2,33,53,32,2,33,53,32,19,22,7,22,23,18,1,160,1,84,20,254,172,1,84,30,254,172,2,9,14,8,132,143, +6,10,153,1,124,153,1,26,152,254,232,158,77,89,188,254,184,0,0,0,1,0,235,1,203,3,244,5,240,0,9,0,0,1,16,23,7,2,53,16,33,21,32,1,165,117,164,139,3,9,253,177,3,205,254,254,210,46,1,49,212,2,32,219,0,0,0,0,1,0,235,0,86,3,244,4,123,0,9,0,0,1,16,23,7,2,53, +16,33,21,32,1,165,117,164,139,3,9,253,177,2,88,254,254,210,46,1,49,212,2,32,189,0,0,0,0,1,0,137,254,86,4,72,5,213,0,21,0,0,1,17,20,7,6,43,1,53,51,50,55,54,53,17,33,17,35,17,51,17,33,17,4,72,89,90,165,205,167,90,45,44,253,215,203,203,2,41,5,213,250,23, +195,105,106,156,62,62,146,2,199,253,57,5,213,253,156,2,100,0,0,0,0,1,0,195,254,86,4,27,6,20,0,29,0,0,1,52,38,35,34,6,21,17,35,17,51,17,62,1,51,50,22,21,17,20,7,6,43,1,53,51,50,55,54,53,3,98,106,113,129,139,184,184,49,168,115,171,169,89,90,165,205,185, +90,45,44,2,182,151,142,183,171,253,135,6,20,253,164,96,99,225,228,253,54,195,105,106,156,62,62,126,0,0,255,255,1,233,0,0,2,229,4,39,18,6,0,29,0,0,0,2,1,136,1,73,3,74,3,11,0,3,0,7,0,0,1,33,53,33,53,33,53,33,3,74,254,62,1,194,254,62,1,194,1,73,150,150, +150,0,0,1,2,4,1,225,2,207,5,213,0,5,0,0,1,51,17,3,35,3,2,4,203,21,161,21,5,213,253,113,254,155,1,101,0,0,0,1,2,16,3,170,2,190,5,213,0,3,0,18,183,1,0,136,4,0,4,2,4,16,212,236,49,0,16,244,196,48,1,17,35,17,2,190,174,5,213,253,213,2,43,0,0,0,255,255,0,137, +0,0,4,68,5,213,18,6,3,102,0,0,0,2,0,157,254,86,4,52,6,31,0,25,0,32,0,0,5,20,22,59,1,21,35,34,38,53,17,35,32,53,52,51,50,23,17,33,53,33,17,51,21,35,39,38,35,34,21,20,51,2,170,91,89,214,232,165,181,62,254,233,246,53,42,254,217,1,223,250,250,184,23,71,78, +92,20,124,126,156,212,194,2,134,189,246,25,1,131,144,252,243,160,160,132,75,57,0,0,1,0,84,254,190,4,149,5,213,0,13,0,0,19,33,1,17,51,17,51,17,35,17,35,1,17,35,84,1,0,1,248,195,134,170,220,254,8,195,5,213,251,51,4,205,250,213,254,20,1,66,4,205,251,51, +0,1,0,122,254,226,4,94,4,123,0,23,0,0,1,17,51,17,35,17,35,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,22,3,210,140,150,175,106,113,129,139,184,184,49,168,115,171,169,2,182,253,224,254,76,1,30,2,182,151,142,183,171,253,135,4,96,168,96,99,225,0,1,0,20, +0,0,4,175,5,213,0,20,0,0,1,34,6,29,1,35,53,52,54,59,1,17,33,17,51,17,35,17,33,17,35,1,82,62,100,156,169,149,203,1,199,203,203,254,57,203,5,47,87,112,49,70,159,185,253,156,2,100,250,43,2,199,253,57,0,2,0,230,2,156,3,235,5,224,0,19,0,23,0,0,1,51,21,33, +53,51,21,51,21,35,17,35,17,33,17,35,17,35,53,51,23,21,33,53,1,58,128,1,93,127,85,85,127,254,163,128,84,84,128,1,93,5,224,125,125,125,92,253,149,1,142,254,114,2,107,92,92,126,126,0,0,3,0,63,2,140,4,146,5,30,0,36,0,48,0,55,0,0,18,32,23,22,23,54,55,54,23, +50,22,29,1,33,21,20,22,51,50,54,55,21,14,1,35,38,39,38,39,6,7,6,35,34,38,53,52,37,34,6,21,20,22,51,50,54,53,52,38,5,46,1,35,34,6,7,218,1,38,78,13,11,11,12,91,151,135,156,254,10,120,109,55,122,69,66,123,58,164,93,14,11,11,13,77,148,147,155,1,46,88,91, +91,88,89,91,91,2,88,3,91,86,84,108,10,5,30,84,15,16,13,13,90,1,162,141,50,3,102,113,31,32,102,24,24,1,87,13,14,16,15,84,168,161,160,82,122,120,119,123,123,119,120,122,185,91,94,99,87,0,0,2,0,137,255,227,4,72,6,21,0,11,0,37,0,0,1,34,6,21,20,22,51,50,54, +53,52,38,39,54,18,17,16,2,35,34,2,17,52,54,55,46,1,53,52,54,51,37,21,33,34,21,20,22,2,104,140,144,144,140,141,144,144,141,232,248,246,234,233,246,123,49,80,65,194,158,1,252,254,40,188,114,3,223,218,214,213,219,219,213,214,218,156,1,254,209,254,226,254, +225,254,211,1,45,1,31,229,216,42,47,142,49,124,148,1,150,135,73,53,0,0,2,0,35,0,0,4,55,6,20,0,3,0,25,0,78,64,42,20,9,22,2,18,14,182,10,5,140,4,2,196,0,155,4,155,10,194,16,12,6,25,9,4,13,0,6,1,4,15,9,6,11,1,74,19,69,21,17,69,26,16,244,60,228,236,50,252, +60,196,16,238,50,17,18,57,57,49,0,47,60,230,236,254,238,16,238,16,238,50,18,57,57,57,48,1,51,21,35,39,21,35,34,6,29,1,33,17,35,17,33,17,35,17,35,53,51,53,52,54,51,3,127,184,184,119,180,99,77,2,147,184,254,37,184,201,201,169,179,6,18,233,235,153,81,103, +101,251,162,3,209,252,47,3,209,143,78,184,174,0,0,0,1,0,35,0,0,4,55,6,20,0,21,0,66,64,35,16,7,18,3,14,10,182,8,3,140,0,155,8,194,12,1,4,21,9,7,2,6,0,9,11,7,6,0,74,15,69,17,13,69,22,16,244,60,228,236,252,60,196,16,238,17,18,57,57,49,0,47,60,230,254,238, +16,238,50,18,57,57,57,48,1,17,35,17,33,34,6,29,1,33,21,33,17,35,17,35,53,51,53,52,54,51,4,55,184,254,213,99,77,1,37,254,219,184,201,201,169,179,6,20,249,236,5,123,81,103,101,141,252,47,3,209,143,78,184,174,255,255,0,69,254,12,4,176,2,27,16,38,13,32,0, +0,16,7,13,26,2,30,255,6,255,255,0,69,254,12,4,229,2,28,16,38,13,20,0,0,16,7,13,26,1,252,255,6,255,255,255,236,254,12,2,188,2,88,16,38,12,38,0,0,16,7,13,26,2,12,255,6,255,255,255,236,254,12,4,229,2,88,16,38,12,39,0,0,16,7,13,26,2,12,255,6,255,255,0,69, +254,12,4,176,2,27,16,38,13,32,0,0,16,7,13,25,1,189,255,6,255,255,0,69,254,12,4,229,2,28,16,38,13,20,0,0,16,7,13,25,1,120,255,6,255,255,255,236,254,12,3,28,2,88,16,38,12,38,0,0,16,7,13,25,1,140,255,6,255,255,255,236,254,12,4,229,2,88,16,38,12,39,0,0,16, +7,13,25,1,140,255,6,255,255,0,69,254,12,4,176,2,27,16,38,13,32,0,0,16,7,13,27,1,147,255,6,255,255,0,69,254,12,4,229,2,28,16,38,13,20,0,0,16,7,13,27,1,114,255,6,255,255,255,236,254,12,3,10,2,88,16,38,12,38,0,0,16,7,13,27,1,122,255,6,255,255,255,236,254, +12,4,229,2,88,16,38,12,39,0,0,16,7,13,27,1,152,255,6,255,255,0,69,255,236,4,176,3,189,16,38,13,32,0,0,16,7,13,26,2,55,3,39,255,255,0,69,255,236,4,229,3,195,16,38,13,20,0,0,16,7,13,26,2,1,3,45,255,255,255,236,0,0,2,188,4,120,16,38,12,38,0,0,16,7,13,26, +2,16,3,226,255,255,255,236,0,0,4,229,4,109,16,38,12,39,0,0,16,7,13,26,2,15,3,215,255,255,0,69,255,236,4,176,4,26,16,38,13,32,0,0,16,7,13,27,1,147,3,132,255,255,0,69,255,236,4,229,4,26,16,39,13,27,1,129,3,132,16,6,13,20,0,0,255,255,255,236,0,0,3,31,4, +121,16,38,12,38,0,0,16,7,13,27,1,143,3,227,255,255,255,236,0,0,4,229,4,124,16,38,12,39,0,0,16,7,13,27,1,140,3,230,255,255,0,69,255,236,4,176,4,87,16,38,13,32,0,0,16,7,4,84,0,76,253,102,255,255,0,69,255,236,4,229,4,72,16,39,4,84,0,52,253,87,16,6,13,20, +0,0,255,255,255,236,0,0,3,184,4,245,16,38,12,38,0,0,16,7,4,84,0,75,254,4,255,255,255,236,0,0,4,229,5,4,16,38,12,39,0,0,16,7,4,84,0,93,254,19,255,255,255,182,255,164,4,140,5,114,16,38,13,40,0,0,16,7,13,19,2,116,3,226,255,255,255,106,255,165,4,229,5,6, +16,39,13,19,2,132,3,118,16,6,13,24,0,0,255,255,255,236,0,0,3,63,6,14,16,39,13,19,1,44,4,126,16,6,13,21,0,0,255,255,255,236,0,0,4,229,5,16,16,39,13,19,1,150,3,128,16,6,13,22,0,0,255,255,255,182,255,164,4,140,5,126,16,38,13,40,0,0,16,7,13,27,2,136,4,232, +255,255,255,106,255,165,4,229,5,10,16,39,13,27,2,140,4,116,16,6,13,24,0,0,255,255,255,236,0,0,3,63,6,14,16,39,13,27,1,44,5,120,16,6,13,21,0,0,255,255,255,236,0,0,4,229,5,32,16,39,13,27,1,154,4,138,16,6,13,22,0,0,255,255,0,88,254,12,4,173,3,102,16,38, +4,99,0,0,16,7,13,26,2,123,0,175,255,255,0,88,254,12,4,249,3,102,16,38,12,93,0,0,16,7,13,26,2,47,0,125,255,255,255,236,254,62,4,92,3,47,16,39,13,26,1,97,255,56,16,6,12,94,0,0,255,255,255,236,254,62,4,252,3,47,16,39,13,26,2,13,255,56,16,6,12,95,0,0,255, +255,0,88,254,12,4,173,3,102,16,38,4,99,0,0,16,7,13,18,2,138,0,25,255,255,0,88,254,12,4,249,3,102,16,38,12,93,0,0,16,7,13,18,2,38,255,231,255,255,255,236,255,56,4,92,3,47,16,39,13,18,0,188,255,56,16,6,12,94,0,0,255,255,255,236,255,56,4,252,3,47,16,39, +13,18,1,144,255,56,16,6,12,95,0,0,255,255,0,88,254,12,4,173,3,102,16,38,4,99,0,0,16,7,13,25,2,42,0,150,255,255,0,88,254,12,4,249,3,102,16,38,12,93,0,0,16,7,13,25,1,197,0,66,255,255,255,236,254,22,4,92,3,47,16,39,13,25,0,240,255,16,16,6,12,94,0,0,255, +255,255,236,254,62,4,252,3,47,16,39,13,25,1,144,255,56,16,6,12,95,0,0,255,255,0,88,254,12,4,173,3,102,16,38,4,99,0,0,16,7,13,27,2,50,0,175,255,255,0,88,254,12,4,249,3,102,16,38,12,93,0,0,16,7,13,27,1,197,0,94,255,255,255,236,254,22,4,92,3,47,16,39,13, +27,0,252,255,16,16,6,12,94,0,0,255,255,255,236,254,62,4,252,3,47,16,39,13,27,1,144,255,56,16,6,12,95,0,0,255,255,255,204,254,8,4,97,4,55,16,38,4,103,0,0,16,7,13,19,2,208,2,166,255,255,255,96,254,12,4,229,4,68,16,39,13,19,2,92,2,180,16,6,12,105,0,0,255, +255,255,204,254,8,4,194,4,155,16,39,4,84,1,85,253,170,16,6,4,103,0,0,255,255,255,96,254,12,4,229,4,132,16,39,4,84,0,233,253,147,16,6,12,105,0,0,255,255,0,10,255,167,5,93,6,20,16,6,4,164,0,0,0,1,255,131,255,167,5,26,6,20,0,50,0,0,37,6,7,6,7,6,35,34,39, +36,17,52,55,51,6,21,20,23,22,51,50,54,55,54,53,52,39,3,38,53,52,55,54,55,1,21,1,6,21,20,23,1,22,59,1,21,35,34,39,38,39,3,245,25,48,81,128,99,207,112,108,254,182,63,184,65,203,79,76,162,218,54,52,41,182,62,18,46,86,2,14,254,104,70,18,1,100,40,40,38,42, +61,35,62,20,182,50,40,73,61,47,32,98,1,11,138,92,94,136,120,72,28,106,60,57,34,49,66,1,44,102,37,84,31,79,65,1,142,209,254,194,55,46,78,29,253,194,63,184,18,30,30,255,255,255,236,0,0,4,43,6,20,16,6,12,150,0,0,255,255,255,236,0,0,4,230,6,20,16,6,12,151, +0,0,255,255,0,10,255,167,5,99,7,71,16,38,4,164,0,0,16,7,13,28,2,172,0,14,255,255,255,131,255,167,5,26,7,74,16,39,13,28,2,84,0,18,16,6,12,25,0,0,255,255,255,236,0,0,4,43,7,57,16,39,13,29,0,143,0,0,16,6,12,26,0,0,255,255,255,236,0,0,4,230,7,57,16,39,13, +29,0,156,0,0,16,6,12,27,0,0,255,255,0,54,254,181,4,141,2,176,16,6,13,42,0,0,0,1,255,213,254,12,4,230,2,12,0,38,0,0,1,6,7,6,35,34,39,38,17,52,55,51,6,21,20,23,22,51,50,55,54,55,54,53,52,39,51,22,23,22,23,22,59,1,21,35,34,39,6,3,200,71,142,140,129,172, +123,234,53,184,55,161,57,129,84,63,157,58,33,101,184,17,35,34,31,35,86,52,94,87,14,6,254,247,116,60,59,63,120,1,18,174,142,174,142,180,67,24,20,51,167,94,119,184,203,51,85,84,56,64,184,48,173,0,0,0,255,255,0,0,255,189,4,147,3,229,16,6,4,166,0,0,0,3,0, +0,0,0,4,242,3,229,0,38,0,54,0,68,0,0,37,51,21,33,34,39,6,7,6,39,38,53,52,55,51,6,21,20,23,22,51,50,55,38,39,38,53,52,55,54,23,38,39,53,22,23,22,23,22,37,54,55,54,53,52,39,38,35,34,7,6,21,20,23,22,37,22,7,6,7,22,51,50,55,54,39,38,39,38,4,144,98,254,136, +190,74,131,164,145,68,118,16,184,14,30,45,40,48,103,58,23,18,45,48,77,44,81,212,227,249,71,24,253,205,36,34,39,15,22,58,65,23,22,7,21,1,71,13,22,25,53,28,39,129,13,5,5,6,20,51,184,184,52,51,1,1,37,64,128,75,53,58,44,43,11,16,16,67,102,78,64,84,83,90, +9,39,14,185,65,182,200,231,79,29,27,64,72,61,46,37,52,45,43,35,30,37,118,188,95,85,91,49,21,67,31,32,34,38,95,0,255,255,255,236,255,189,3,227,3,229,16,6,12,166,0,0,0,3,255,236,0,0,4,242,3,229,0,28,0,44,0,58,0,0,37,38,39,38,53,52,55,54,23,38,39,53,22, +23,22,23,22,7,51,21,33,34,39,6,43,1,53,51,50,55,54,55,54,53,52,39,38,35,34,7,6,21,20,23,22,37,22,7,6,7,22,51,50,55,54,39,38,39,38,1,92,58,23,18,45,48,77,44,81,212,227,249,71,24,13,202,254,32,190,74,134,161,247,238,70,226,36,34,39,15,22,58,65,23,22,7, +21,1,71,13,22,25,53,28,39,129,13,5,5,6,20,51,200,67,102,78,64,84,83,90,9,39,14,185,65,182,200,231,79,56,184,52,52,184,85,27,64,72,61,46,37,52,45,43,35,30,37,118,188,95,85,91,49,21,67,31,32,34,38,95,0,0,0,1,255,236,0,0,2,188,2,88,0,13,0,0,37,6,33,35,53, +51,32,55,54,61,1,51,21,20,2,96,72,254,169,213,158,1,29,44,49,184,86,86,184,44,49,106,217,217,187,0,0,0,0,1,255,236,0,0,4,229,2,88,0,20,0,0,37,6,35,33,53,33,50,55,54,61,1,51,21,20,23,22,51,33,21,33,34,2,94,76,215,254,177,1,24,162,44,48,184,50,44,163,1, +42,254,159,214,86,86,184,44,49,106,217,217,106,49,44,184,0,255,255,0,25,254,243,4,209,3,28,16,6,4,122,0,0,255,255,255,124,254,240,4,229,2,2,16,6,12,171,0,0,255,255,255,236,254,212,3,23,2,88,16,39,13,18,1,135,254,212,16,6,12,38,0,0,255,255,255,236,254, +212,4,229,2,88,16,39,13,18,1,147,254,212,16,6,12,39,0,0,255,255,1,68,4,186,3,140,6,154,16,6,4,124,0,0,255,255,255,236,0,0,4,229,6,154,16,38,4,124,0,0,16,6,4,113,0,0,0,0,255,255,1,68,4,186,3,140,6,253,16,6,4,125,0,0,0,1,3,34,0,0,4,229,1,107,0,13,0,0,1, +20,23,22,59,1,21,35,34,39,38,61,1,51,3,218,49,44,99,75,130,142,92,87,184,1,76,55,49,44,184,92,87,141,43,0,0,0,255,255,1,68,254,22,3,140,255,246,16,6,4,126,0,0,255,255,1,68,4,186,3,140,5,170,16,6,4,127,0,0,255,255,255,236,0,0,4,229,5,170,16,38,4,113,0, +0,16,6,4,127,0,0,0,0,255,255,1,68,4,185,3,140,6,253,16,6,4,128,0,0,255,255,255,236,0,0,4,229,6,253,16,38,4,113,0,0,16,6,4,128,0,0,0,0,255,255,1,68,254,232,3,140,255,216,16,6,4,129,0,0,255,255,255,236,254,232,4,229,0,184,16,38,4,113,0,0,16,6,4,129,0,0, +0,0,255,255,1,48,4,203,3,160,6,244,16,6,4,130,0,0,255,255,255,236,0,0,4,229,6,244,16,38,4,113,0,0,16,6,4,130,0,0,0,0,255,255,1,86,4,225,3,122,7,6,16,6,4,131,0,0,255,255,255,236,0,0,4,229,7,6,16,38,4,131,0,0,16,6,4,113,0,0,0,0,255,255,1,178,0,85,4,45, +3,222,16,6,4,87,0,0,255,255,1,0,0,0,3,208,7,131,16,38,4,93,0,0,16,7,4,132,0,0,1,194,255,255,1,0,0,0,4,230,7,131,16,39,4,132,0,0,1,194,16,6,12,73,0,0,255,255,1,179,0,0,3,10,8,57,16,38,4,93,0,0,16,7,4,133,255,246,1,194,255,255,1,228,0,0,4,230,8,57,16,39, +4,133,0,39,1,194,16,6,12,73,0,0,255,255,0,76,254,12,4,51,4,181,16,38,4,121,0,0,16,7,4,133,0,96,254,62,255,255,0,90,254,12,4,229,4,181,16,39,4,133,0,50,254,62,16,6,12,169,0,0,255,255,1,182,254,12,3,13,6,20,16,38,4,93,0,0,16,6,4,134,249,0,0,0,255,255,2, +19,254,12,4,230,6,20,16,38,4,134,86,0,16,6,12,73,0,0,0,0,255,255,0,25,254,243,4,209,4,86,16,38,4,122,0,0,16,7,4,133,255,89,253,223,255,255,255,124,254,240,4,229,3,95,16,39,4,133,254,228,252,232,16,6,12,171,0,0,255,255,255,236,0,0,2,254,4,231,16,39,4, +133,255,234,254,112,16,6,12,38,0,0,255,255,255,236,0,0,4,229,4,231,16,39,4,133,0,0,254,112,16,6,12,39,0,0,255,255,2,12,0,0,2,196,6,20,16,6,4,93,0,0,0,1,2,76,0,0,4,230,6,20,0,13,0,0,1,17,51,17,20,23,22,59,1,21,33,34,39,38,2,76,184,50,44,180,208,254,248, +234,80,88,1,115,4,161,251,107,106,49,44,184,92,101,255,255,0,69,254,162,4,176,2,27,16,38,13,32,0,0,16,7,13,17,2,27,254,162,255,255,0,69,254,162,4,229,2,28,16,39,13,17,1,209,254,162,16,6,13,20,0,0,255,255,255,236,254,212,2,188,2,88,16,38,12,38,0,0,16, +7,13,17,1,248,254,212,255,255,255,236,254,212,4,229,2,88,16,38,12,39,0,0,16,7,13,17,2,20,254,212,255,255,0,222,255,198,3,243,4,26,16,38,4,120,0,0,16,7,13,18,1,106,3,132,255,255,0,242,0,0,4,229,4,26,16,39,13,18,1,198,3,132,16,6,12,165,0,0,255,255,0,69, +255,236,4,176,3,32,16,38,13,32,0,0,16,7,13,18,1,191,2,138,255,255,0,69,255,236,4,229,3,32,16,39,13,18,1,156,2,138,16,6,13,20,0,0,255,255,255,236,0,0,3,35,3,232,16,39,13,18,1,147,3,82,16,6,12,38,0,0,255,255,255,236,0,0,4,229,3,232,16,39,13,18,1,147,3, +82,16,6,12,39,0,0,255,255,0,69,255,236,4,176,4,26,16,38,13,32,0,0,16,7,13,19,1,186,2,138,255,255,0,69,255,236,4,229,4,26,16,39,13,19,1,168,2,138,16,6,13,20,0,0,255,255,255,236,0,0,3,44,4,226,16,38,12,38,0,0,16,7,13,19,1,156,3,82,255,255,255,236,0,0,4, +229,4,188,16,38,12,39,0,0,16,7,13,19,1,155,3,44,255,255,0,88,254,12,4,173,3,102,16,38,4,99,0,0,16,7,13,17,2,159,0,25,255,255,0,88,254,12,4,249,3,102,16,39,13,17,2,112,255,206,16,6,12,93,0,0,255,255,255,236,254,212,4,92,3,47,16,39,13,17,2,13,254,212,16, +6,12,94,0,0,255,255,255,236,254,212,4,252,3,47,16,39,13,17,2,13,254,212,16,6,12,95,0,0,255,255,0,88,254,12,4,173,3,102,16,6,4,99,0,0,0,1,0,88,254,12,4,249,3,102,0,46,0,0,37,51,21,35,34,39,38,39,38,39,6,7,6,21,20,23,22,5,50,55,21,6,7,4,39,38,53,16,55, +54,55,38,7,6,7,53,36,23,4,23,21,6,7,23,22,23,22,4,209,40,49,129,123,82,61,6,73,114,98,224,74,129,1,19,193,212,150,250,254,148,169,131,212,96,137,101,159,135,95,1,20,195,1,36,196,109,31,29,51,72,90,184,184,150,100,156,15,178,24,80,183,252,138,93,163,1, +118,184,98,1,2,196,152,222,1,2,223,101,52,3,22,19,41,184,64,1,1,53,154,3,10,91,160,95,119,0,0,0,0,1,255,236,0,0,4,92,3,47,0,30,0,0,1,38,39,38,39,38,7,53,54,55,50,23,4,23,21,6,7,6,7,6,7,6,43,1,53,51,50,55,54,55,54,3,83,83,103,85,180,82,161,72,75,162,172, +1,2,220,76,88,166,74,145,75,221,163,128,100,227,129,104,116,94,2,29,23,23,19,16,7,6,184,7,1,35,52,98,154,24,52,98,66,129,27,80,184,72,58,106,86,0,0,0,1,255,236,0,0,4,252,3,47,0,41,0,0,1,4,23,21,6,7,22,23,22,59,1,21,35,34,39,38,39,6,7,6,7,6,43,1,53,51, +50,55,54,55,54,55,38,39,38,39,38,7,53,54,55,50,2,126,1,2,220,65,73,50,30,104,54,60,80,151,124,40,59,69,41,145,75,221,163,128,100,227,129,104,116,94,101,83,103,85,180,82,161,72,75,162,3,12,52,98,154,20,41,78,34,119,184,168,54,97,46,37,129,27,80,184,72, +58,106,86,35,23,23,19,16,7,6,184,7,1,0,0,255,255,0,88,254,12,4,173,4,176,16,38,4,99,0,0,16,7,13,17,1,220,4,26,255,255,0,88,254,12,4,249,4,176,16,39,13,17,1,216,4,26,16,6,12,93,0,0,255,255,255,236,0,0,4,92,4,76,16,39,13,17,2,13,3,182,16,6,12,94,0,0,255, +255,255,236,0,0,4,252,4,76,16,39,13,17,2,13,3,182,16,6,12,95,0,0,255,255,0,232,255,218,3,232,3,106,16,6,4,101,0,0,0,1,0,232,255,218,4,229,3,106,0,32,0,0,1,20,23,22,59,1,21,35,34,39,6,7,6,35,34,39,53,22,51,50,55,54,55,54,53,52,39,38,39,51,22,23,22,3,232, +82,44,99,28,83,147,97,94,206,46,94,151,103,115,133,82,34,173,34,8,60,69,170,227,107,72,82,1,122,68,82,44,184,130,130,31,7,38,184,42,9,46,115,27,42,93,101,115,184,108,131,149,0,0,0,255,255,0,232,255,218,3,232,4,176,16,38,4,101,0,0,16,7,13,17,2,12,4,26, +255,255,0,232,255,218,4,229,4,176,16,39,13,17,2,21,4,26,16,6,12,101,0,0,255,255,255,204,254,8,4,68,2,34,16,6,4,103,0,0,0,1,255,96,254,12,4,229,2,38,0,24,0,0,1,51,22,23,22,23,22,59,1,21,35,34,39,6,5,4,33,53,32,55,36,55,54,53,52,2,238,184,30,3,10,73,42, +101,60,115,130,50,57,254,215,254,228,254,32,1,189,219,0,255,34,10,2,38,112,30,103,77,44,184,62,253,158,151,184,128,149,197,58,72,126,0,0,0,255,255,255,204,254,8,4,68,3,182,16,38,4,103,0,0,16,7,13,17,3,93,3,32,255,255,255,96,254,12,4,229,3,182,16,39,13, +17,2,239,3,32,16,6,12,105,0,0,255,255,255,36,254,20,4,152,2,238,16,6,4,105,0,0,0,1,254,216,254,20,4,229,2,238,0,70,0,0,5,34,39,38,39,6,7,6,7,6,39,6,7,6,7,6,35,34,39,38,55,54,55,51,6,23,22,23,22,51,50,55,54,55,54,39,38,47,1,51,23,22,23,22,23,22,55,54, +53,51,6,23,22,51,50,25,1,51,17,20,23,22,59,1,21,35,34,39,6,7,6,3,52,65,25,64,26,31,69,50,74,47,49,8,30,37,61,71,113,95,101,118,18,20,60,164,87,5,8,33,46,48,53,50,35,26,24,2,1,16,41,159,18,17,21,49,39,47,45,37,164,4,37,32,42,105,164,41,44,59,8,63,100, +60,31,71,33,29,25,67,126,109,56,40,2,2,80,168,94,121,77,92,100,115,213,232,130,225,137,172,43,59,72,50,122,109,165,94,92,234,156,145,35,80,3,3,125,103,194,163,141,120,1,24,1,38,254,170,139,41,44,184,96,97,19,9,0,0,0,1,255,236,255,221,4,148,2,232,0,49, +0,0,37,50,55,54,53,51,6,23,22,51,50,25,1,51,17,20,7,6,7,6,35,34,39,38,39,6,7,6,35,34,39,38,39,6,7,6,43,1,53,51,50,55,54,61,1,51,21,20,23,22,1,230,67,42,37,165,5,38,31,43,104,164,62,33,85,22,78,66,24,65,25,31,70,51,73,50,81,44,12,21,69,59,101,70,42,76, +36,70,164,26,21,181,116,103,194,163,141,120,1,24,1,38,254,170,159,153,82,34,9,25,67,126,109,56,42,64,35,63,57,44,37,184,35,71,118,192,156,79,100,84,0,1,255,236,255,221,4,230,2,232,0,55,0,0,1,20,23,22,51,50,25,1,51,17,20,23,22,59,1,21,35,34,39,6,7,6,35, +34,39,38,39,6,7,6,35,34,39,38,39,6,7,6,43,1,53,51,50,55,54,61,1,51,21,20,23,22,50,55,54,53,2,209,33,29,53,100,164,42,44,34,34,64,101,59,54,58,22,72,79,55,42,12,30,70,51,53,67,37,38,24,20,70,58,68,70,42,55,31,64,162,26,22,96,42,37,2,82,166,138,120,1,24, +1,38,254,170,139,41,44,184,96,88,27,10,73,54,91,109,56,42,54,55,53,57,44,37,184,35,71,118,192,156,79,100,84,116,103,194,0,0,255,255,255,36,254,20,4,152,4,176,16,38,4,105,0,0,16,7,13,19,1,54,3,32,255,255,254,216,254,20,4,229,4,176,16,39,13,19,0,236,3, +32,16,6,12,109,0,0,255,255,255,236,255,221,4,148,4,176,16,39,13,19,1,150,3,32,16,6,12,110,0,0,255,255,255,236,255,221,4,230,4,176,16,39,13,19,1,82,3,32,16,6,12,111,0,0,255,255,255,16,254,20,4,192,2,143,16,6,4,107,0,0,0,2,254,197,254,20,4,229,2,143,0, +12,0,71,0,0,37,51,50,55,54,53,52,39,38,35,34,7,6,37,20,7,22,23,22,59,1,21,35,34,47,1,6,43,1,34,39,38,53,20,7,6,7,6,35,34,39,38,53,52,55,51,6,21,20,23,22,55,54,55,54,53,52,39,38,39,51,6,23,22,23,54,55,54,51,50,23,22,1,253,129,140,73,106,40,36,63,71,104, +75,2,61,31,16,14,46,28,39,59,52,102,28,172,136,218,38,52,45,47,47,51,102,74,130,90,125,101,172,104,60,50,60,67,37,64,9,33,13,171,1,14,10,40,76,49,146,150,171,91,87,184,46,68,70,45,37,33,109,78,78,52,71,10,13,44,184,94,26,120,30,26,16,175,131,129,43,86, +90,125,205,188,172,204,156,145,50,41,3,4,59,103,139,104,62,212,72,15,55,40,50,128,60,177,82,78,0,0,0,0,2,255,236,0,0,4,193,2,143,0,12,0,44,0,0,37,51,50,55,54,53,52,39,38,35,34,7,6,3,34,39,38,39,6,43,1,53,51,50,55,54,61,1,51,21,20,22,23,54,55,54,51,50, +23,22,21,20,7,6,35,2,73,129,140,73,106,40,36,63,71,104,75,82,74,78,65,39,102,94,130,75,43,37,65,184,18,45,76,49,146,150,171,91,87,184,126,127,184,46,68,70,45,37,33,109,78,254,216,42,35,61,138,184,44,80,100,114,78,24,80,50,128,60,177,82,78,121,190,109, +75,0,0,2,255,236,0,0,4,229,2,143,0,12,0,54,0,0,37,51,50,55,54,53,52,39,38,35,34,7,6,3,34,39,38,39,6,43,1,53,51,50,55,54,61,1,51,21,20,22,23,54,55,54,51,50,23,22,21,20,7,22,23,22,59,1,21,35,34,47,1,6,35,1,253,129,140,73,106,40,36,63,71,104,75,82,74,78, +65,39,102,68,80,26,31,42,45,184,18,45,76,49,146,150,171,91,87,31,16,14,46,28,39,59,52,102,28,172,136,184,46,68,70,45,37,33,109,78,254,216,42,35,61,138,184,46,50,128,114,78,24,80,50,128,60,177,82,78,121,52,71,10,13,44,184,94,26,120,255,255,255,16,254, +20,4,192,3,52,16,38,4,107,0,0,16,7,13,17,1,79,2,158,255,255,254,197,254,20,4,229,3,52,16,39,13,17,1,4,2,158,16,6,12,117,0,0,255,255,255,236,0,0,4,193,3,118,16,39,13,17,1,87,2,224,16,6,12,118,0,0,255,255,255,236,0,0,4,229,3,104,16,39,13,17,1,52,2,210, +16,6,12,119,0,0,255,255,0,10,0,0,4,164,6,20,16,6,4,109,0,0,0,2,0,20,0,0,4,229,6,20,0,12,0,39,0,0,37,51,50,55,54,53,52,39,38,35,34,7,6,37,20,7,22,59,1,21,35,34,47,1,6,35,33,35,53,51,17,51,17,54,55,54,51,50,23,22,2,8,129,140,73,106,40,36,63,71,104,75,2, +61,42,61,37,45,58,93,85,28,125,149,253,251,178,178,184,76,49,146,150,171,91,87,184,46,68,70,45,37,33,109,78,78,53,70,67,184,79,26,105,184,5,92,251,14,128,60,177,82,78,0,0,2,255,236,0,0,4,164,6,20,0,12,0,31,0,0,37,51,50,55,54,53,52,39,38,35,34,7,6,19, +33,35,53,51,17,51,17,54,55,54,51,50,23,22,21,20,7,6,2,44,129,140,73,106,40,36,63,71,104,75,136,253,251,254,254,184,76,49,142,154,171,91,87,184,126,184,46,68,70,45,37,33,109,78,254,216,184,5,92,251,14,128,60,177,82,78,121,190,109,75,0,2,255,236,0,0,4, +229,6,20,0,12,0,39,0,0,37,51,50,55,54,53,52,39,38,35,34,7,6,37,20,7,22,59,1,21,35,34,47,1,6,35,33,35,53,51,17,51,17,54,55,54,51,50,23,22,2,8,129,140,73,106,40,36,63,71,104,75,2,61,42,61,37,45,58,93,85,28,125,149,253,251,218,218,184,76,49,146,150,171, +91,87,184,46,68,70,45,37,33,109,78,78,53,70,67,184,79,26,105,184,5,92,251,14,128,60,177,82,78,0,255,255,0,10,0,0,4,164,6,20,16,38,4,109,0,0,16,7,13,17,2,67,3,0,255,255,0,20,0,0,4,229,6,20,16,39,13,17,2,67,3,0,16,6,12,125,0,0,255,255,255,236,0,0,4,164, +6,20,16,39,13,17,2,67,3,0,16,6,12,126,0,0,255,255,255,236,0,0,4,229,6,20,16,39,13,17,2,67,3,0,16,6,12,127,0,0,255,255,0,122,254,12,4,183,4,42,16,6,4,111,0,0,0,2,0,148,254,12,4,244,3,14,0,44,0,55,0,0,51,52,55,38,39,38,53,52,55,54,55,54,50,23,22,23,22, +21,20,7,6,7,22,23,22,59,1,21,35,32,39,6,21,20,23,22,33,50,55,21,6,7,4,39,38,0,34,7,6,21,20,23,54,55,54,39,148,187,61,38,30,13,16,104,89,238,89,101,19,13,69,118,55,68,87,95,148,224,208,254,183,248,154,41,107,1,95,193,212,150,250,254,82,157,98,1,169,52, +30,47,70,134,2,1,48,212,140,50,72,57,27,31,41,55,52,45,45,51,56,38,34,62,56,96,19,64,37,40,184,228,129,106,109,61,158,118,184,98,1,2,190,119,3,22,7,12,32,36,65,55,46,32,12,0,0,0,0,1,255,236,0,0,3,249,4,42,0,26,0,0,55,50,55,38,39,38,53,16,55,54,51,21, +34,6,20,23,22,51,50,55,37,21,5,4,43,1,53,61,161,202,75,52,88,204,125,251,218,186,62,83,70,56,73,1,32,254,92,254,162,178,89,184,93,24,59,100,140,1,8,125,77,169,137,255,52,70,33,129,184,197,164,184,0,0,0,2,255,236,0,0,4,229,3,14,0,36,0,47,0,0,37,6,43,1, +53,51,50,55,54,55,38,39,38,53,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,22,23,22,59,1,21,35,34,2,34,7,6,21,20,23,54,53,52,39,2,104,194,202,240,218,107,66,59,40,97,68,30,13,16,104,89,238,89,102,18,13,30,77,88,31,68,61,112,219,241,202,168,52,30,47,103, +103,47,185,185,184,40,36,39,85,90,39,45,31,41,55,52,45,45,51,56,41,31,45,39,98,77,31,44,40,184,2,85,7,12,32,29,95,95,29,32,12,0,0,255,255,0,122,254,12,4,183,5,70,16,38,4,111,0,0,16,7,13,17,1,119,4,176,255,255,0,148,254,12,4,244,4,76,16,39,13,17,1,214, +3,182,16,6,12,133,0,0,255,255,255,236,0,0,3,249,5,70,16,39,13,17,1,119,4,176,16,6,12,134,0,0,255,255,255,236,0,0,4,229,4,76,16,39,13,17,2,27,3,182,16,6,12,135,0,0,255,255,255,182,255,164,4,140,4,192,16,38,13,40,0,0,16,7,13,17,2,240,4,42,255,255,255,106, +255,165,4,229,4,76,16,39,13,17,2,246,3,182,16,6,13,24,0,0,255,255,255,236,0,0,3,63,5,20,16,39,13,17,1,169,4,126,16,6,13,21,0,0,255,255,255,236,0,0,4,229,4,126,16,39,13,17,2,34,3,232,16,6,13,22,0,0,255,255,0,31,254,125,4,116,5,20,16,38,13,33,0,0,16,7, +13,18,2,93,4,126,255,255,255,237,254,20,4,229,4,1,16,39,13,18,2,78,3,107,16,6,13,23,0,0,255,255,255,236,0,0,3,63,5,20,16,38,13,21,0,0,16,7,13,18,1,44,4,126,255,255,255,236,0,0,4,229,4,126,16,38,13,22,0,0,16,7,13,18,1,150,3,232,255,255,0,8,255,201,4,159, +6,20,16,6,4,116,0,0,0,2,255,161,255,201,4,229,6,20,0,33,0,68,0,0,1,21,6,7,6,21,20,23,22,23,22,21,20,7,6,35,34,39,53,22,51,50,55,54,53,52,39,38,39,38,55,54,55,54,1,17,20,23,22,59,1,21,35,34,39,6,7,6,7,6,39,38,53,52,55,51,6,21,20,23,22,51,50,55,54,55,54, +25,1,2,20,74,38,80,14,12,68,102,88,82,78,66,56,68,45,60,57,60,78,74,18,32,1,2,75,85,2,130,49,44,26,75,130,80,113,91,79,103,199,173,163,217,16,184,14,154,121,87,117,98,81,74,52,4,76,82,4,14,30,33,28,18,16,10,15,88,110,42,39,11,88,10,26,26,30,38,17,16, +28,47,46,81,38,43,1,204,251,107,106,49,44,184,123,78,45,53,2,2,57,76,184,75,53,58,44,93,45,35,38,35,95,67,1,7,3,177,0,0,0,1,255,236,0,0,4,43,6,20,0,31,0,0,41,1,53,33,50,55,54,53,52,39,1,38,53,52,55,54,55,1,21,5,6,7,6,21,20,23,1,22,21,20,7,6,1,146,254, +90,1,146,147,46,16,54,254,202,50,10,31,104,2,233,253,173,71,21,6,31,1,19,102,62,95,184,104,36,36,69,66,1,124,61,81,30,38,118,43,1,54,186,250,30,40,11,25,32,37,254,182,122,124,113,101,155,0,0,0,1,255,236,0,0,4,230,6,20,0,41,0,0,41,1,53,33,50,55,54,53, +52,39,1,38,53,52,55,54,55,1,21,5,6,7,6,21,20,23,1,22,23,22,59,1,21,35,34,39,38,47,1,6,7,6,1,156,254,80,1,156,147,47,16,54,254,202,50,10,30,104,2,234,253,172,70,22,6,32,2,70,22,38,44,64,88,132,66,58,102,34,96,22,16,96,184,104,36,36,69,66,1,124,61,81,30, +38,118,43,1,54,186,250,30,40,11,25,32,37,253,63,26,14,16,184,24,43,41,120,46,27,155,0,0,0,255,255,0,67,254,200,4,75,6,20,16,6,4,117,0,0,0,1,0,10,254,200,4,229,6,20,0,36,0,0,1,17,20,23,22,59,1,21,35,34,39,6,7,6,7,6,35,34,39,38,3,38,55,51,6,21,20,23,22, +51,50,55,54,55,54,25,1,4,18,49,44,43,75,130,56,78,15,51,104,129,94,125,99,119,242,1,1,64,184,65,166,40,73,105,84,99,69,30,6,20,251,107,106,49,44,184,51,93,63,126,47,34,42,86,1,3,138,92,115,115,126,66,16,34,41,131,57,1,40,4,106,0,0,1,255,236,0,0,3,233, +6,20,0,13,0,0,1,20,7,6,41,1,53,33,50,55,54,53,17,51,3,233,87,80,254,240,253,186,2,14,218,44,49,184,1,115,178,101,92,184,44,49,106,4,149,0,0,0,0,1,255,236,0,0,4,229,6,20,0,20,0,0,37,6,41,1,53,51,50,55,54,53,17,51,17,20,23,22,59,1,21,33,32,2,104,76,254, +240,254,224,234,218,44,48,184,50,44,218,233,254,223,254,244,86,86,184,44,49,106,4,149,251,107,106,49,44,184,0,0,0,255,255,0,130,254,20,4,84,2,243,16,6,4,118,0,0,0,2,0,71,254,20,4,229,2,116,0,17,0,52,0,0,37,22,51,50,55,54,53,52,39,38,39,38,35,34,7,6,21, +20,5,6,7,6,35,34,39,38,7,6,21,17,35,17,52,55,54,51,38,53,52,55,54,51,50,23,22,23,30,1,59,1,21,35,34,2,12,122,76,44,21,53,6,21,59,40,46,59,27,68,1,192,15,13,133,75,210,112,35,73,25,200,120,65,73,2,162,77,92,72,84,170,40,14,82,102,31,86,173,168,42,22,57, +58,24,20,88,17,12,27,68,68,40,169,14,8,80,78,25,75,26,79,254,147,1,109,173,102,55,42,40,148,132,63,36,71,179,64,94,184,0,0,0,2,255,236,255,206,3,166,2,109,0,24,0,42,0,0,37,6,7,6,39,6,43,1,53,51,50,55,54,55,54,55,54,51,50,23,22,23,22,21,20,37,22,51,50, +55,54,53,52,39,38,39,38,35,34,7,6,7,6,3,100,96,140,212,112,64,104,160,116,52,44,43,5,20,135,94,93,69,69,189,21,4,253,240,62,159,47,19,52,5,22,58,39,39,53,41,50,15,7,52,101,1,2,100,48,184,36,35,49,181,80,56,29,79,171,36,42,142,77,69,18,53,69,19,18,88, +17,12,27,33,97,37,0,2,255,236,255,206,4,229,2,109,0,29,0,47,0,0,37,6,35,34,39,6,43,1,53,51,50,55,54,55,54,55,54,51,50,23,22,23,22,23,22,59,1,21,35,34,37,22,51,50,55,54,53,52,39,38,39,38,35,34,7,6,7,6,3,124,97,139,214,110,64,104,184,140,52,44,43,5,20, +135,94,93,72,66,193,17,5,51,38,105,100,155,174,254,18,62,159,47,19,52,5,22,58,39,39,53,41,46,19,7,52,102,98,48,184,36,35,49,181,80,56,29,83,167,49,62,47,184,199,69,18,53,69,19,18,88,17,12,27,30,100,37,0,0,255,255,0,54,254,181,4,141,3,132,16,38,13,42, +0,0,16,7,13,17,1,211,2,238,255,255,255,213,254,12,4,230,2,175,16,39,13,17,1,119,2,25,16,6,12,33,0,0,255,255,255,236,0,0,2,188,3,232,16,38,12,38,0,0,16,7,13,17,2,16,3,82,255,255,255,236,0,0,4,229,3,232,16,38,12,39,0,0,16,7,13,17,2,21,3,82,255,255,0,222, +255,198,3,243,2,222,16,6,4,120,0,0,0,2,0,242,0,0,4,229,2,238,0,10,0,36,0,0,1,38,39,38,39,6,7,6,23,30,1,19,38,39,51,22,23,22,23,22,59,1,21,35,34,39,38,39,6,35,34,39,38,53,52,55,54,3,5,15,13,13,12,120,82,111,2,1,180,116,4,3,184,1,36,21,56,31,112,113,168, +90,73,45,38,138,156,56,58,189,204,109,1,26,42,49,50,101,12,67,89,62,41,50,1,209,39,43,168,174,101,79,44,184,51,31,59,73,15,48,154,173,127,68,0,3,255,236,255,189,3,227,3,229,0,15,0,45,0,61,0,0,1,54,55,54,53,52,39,38,35,34,7,6,21,20,23,22,7,50,55,38,39, +38,53,52,55,54,23,38,39,53,22,23,4,23,22,21,20,7,6,35,34,39,6,43,1,53,1,22,21,20,7,6,7,22,51,50,55,54,53,52,39,38,1,186,36,34,39,15,22,58,65,23,22,7,21,249,52,78,45,15,18,45,48,77,44,81,219,220,1,5,59,14,40,74,175,131,154,120,146,175,2,209,6,98,12,17, +52,49,126,16,7,33,29,1,13,27,64,72,61,46,37,52,45,43,35,30,37,118,136,11,105,69,78,64,84,83,90,9,39,14,185,67,180,214,217,52,57,103,61,113,108,41,184,1,68,37,39,138,114,14,19,46,67,30,33,60,78,69,0,0,0,3,255,236,254,13,4,229,2,171,0,10,0,36,0,47,0,0, +37,51,50,55,54,53,52,35,34,7,6,7,18,55,54,51,50,23,22,21,20,7,33,21,33,22,21,20,7,6,35,34,39,38,3,33,53,5,20,23,22,51,50,53,52,39,38,35,1,228,19,42,96,114,84,75,74,38,184,9,129,108,129,138,69,46,163,1,232,254,24,163,46,69,138,129,108,129,9,254,192,1, +248,38,74,75,84,114,96,42,184,76,90,52,112,141,72,117,1,10,126,107,99,67,114,111,108,184,108,111,114,67,99,107,128,1,8,184,184,117,72,141,112,52,90,76,255,255,0,76,254,12,4,51,2,134,16,6,4,121,0,0,0,2,0,90,254,12,4,229,2,134,0,11,0,44,0,0,37,52,39,38, +39,38,7,6,7,6,23,22,5,51,21,35,39,6,7,6,7,6,33,53,32,55,54,55,38,39,38,39,38,39,38,55,54,55,54,23,22,23,22,23,22,3,60,16,24,46,60,60,67,13,17,64,47,1,115,246,194,70,25,129,83,105,192,254,147,1,105,132,168,62,118,45,139,51,106,10,2,10,27,176,59,65,87, +69,133,22,13,184,76,57,80,30,41,26,29,56,75,54,40,4,184,1,156,129,83,47,86,184,76,95,148,3,7,24,43,89,135,31,57,155,75,25,1,2,49,92,141,83,255,255,0,25,254,243,4,209,3,28,16,6,4,122,0,0,0,1,255,124,254,240,4,229,2,2,0,55,0,0,37,38,39,38,39,38,53,52,55, +54,55,54,51,50,23,22,59,1,21,35,34,39,38,35,6,7,6,21,20,23,22,21,20,7,6,7,6,35,34,39,38,39,38,55,51,6,21,22,23,22,51,50,55,54,55,54,3,1,2,9,24,24,44,41,77,87,29,44,130,46,64,34,35,35,127,67,64,30,34,16,20,42,53,78,104,181,140,76,121,147,228,12,6,36,178, +26,1,141,69,113,130,58,128,20,60,51,44,12,36,25,46,61,78,47,91,17,6,138,192,184,172,165,1,16,18,32,3,69,87,60,83,83,111,26,20,36,56,198,92,138,80,116,106,26,13,17,37,15,46,0,255,255,0,25,254,12,4,209,3,28,16,38,4,122,0,0,16,7,13,18,1,89,254,12,255,255, +255,124,254,12,4,229,2,2,16,38,12,171,0,0,16,7,13,18,0,192,254,12,255,255,255,236,254,212,3,18,2,88,16,39,13,18,1,130,254,212,16,6,12,38,0,0,255,255,255,236,254,212,4,229,2,88,16,39,13,18,1,147,254,212,16,6,12,39,0,0,255,255,255,150,255,236,4,30,6,237, +16,39,4,132,254,150,1,44,16,6,12,182,0,0,255,255,255,64,255,236,4,229,6,237,16,39,4,132,254,64,1,44,16,6,12,183,0,0,255,255,0,83,255,236,4,30,7,163,16,39,4,133,254,150,1,44,16,6,12,182,0,0,255,255,255,224,255,236,4,229,7,163,16,39,4,133,254,35,1,44,16, +6,12,183,0,0,255,255,0,133,254,12,4,30,6,20,16,39,4,134,254,200,0,0,16,6,12,182,0,0,255,255,0,95,254,12,4,229,6,20,16,39,4,134,254,200,0,0,16,6,12,183,0,0,0,1,0,179,255,236,4,30,6,20,0,22,0,0,1,16,7,6,7,6,35,34,39,53,22,51,50,55,1,51,1,54,55,54,53,17, +51,4,30,139,55,77,205,158,106,75,96,85,113,136,254,22,179,1,170,29,20,37,184,3,66,254,212,218,85,71,180,32,184,32,152,4,70,252,65,43,55,137,184,2,174,0,0,0,0,1,0,95,255,236,4,229,6,20,0,31,0,0,1,6,7,6,35,34,39,53,22,51,50,55,1,51,1,54,55,54,53,17,51, +17,20,23,22,59,1,21,35,34,39,38,3,63,59,73,202,161,106,75,96,85,113,136,254,22,179,1,170,29,20,37,184,34,64,80,105,129,175,102,17,1,60,91,65,180,32,184,32,152,4,70,252,65,43,55,137,184,2,174,252,68,174,84,158,184,243,41,0,0,0,3,0,82,255,84,4,126,7,24, +0,5,0,38,0,42,0,0,9,1,17,9,1,17,1,53,52,55,54,63,1,54,55,54,53,52,38,35,34,6,7,21,62,1,51,50,22,21,20,6,15,1,6,7,6,29,1,7,21,51,53,2,104,2,22,253,234,253,234,2,117,19,18,70,88,94,34,33,221,186,104,191,94,98,178,78,109,131,47,62,90,85,29,31,7,203,7,24, +254,23,252,14,254,23,1,233,3,242,252,98,170,61,42,40,68,86,92,66,65,76,161,192,56,57,188,68,69,110,89,49,88,59,89,84,66,69,98,154,147,254,254,0,0,0,0,3,0,178,0,0,4,68,6,20,0,9,0,13,0,17,0,0,1,33,17,33,21,33,53,33,17,35,1,51,17,35,3,51,21,35,1,0,2,33, +1,35,252,110,1,33,211,1,55,134,134,25,184,184,4,96,252,4,100,100,3,152,252,104,3,152,2,24,233,0,0,0,255,255,0,37,0,0,4,172,5,213,16,6,0,36,0,0,255,255,0,166,0,0,4,113,5,213,16,6,0,37,0,0,255,255,0,139,255,227,4,49,5,240,16,6,0,38,0,0,255,255,0,137,0, +0,4,82,5,213,16,6,0,39,0,0,255,255,0,197,0,0,4,78,5,213,16,6,0,40,0,0,255,255,0,233,0,0,4,88,5,213,16,6,0,41,0,0,255,255,0,102,255,227,4,80,5,240,16,6,0,42,0,0,255,255,0,137,0,0,4,72,5,213,16,6,0,43,0,0,255,255,0,201,0,0,4,6,5,213,16,6,0,44,0,0,255,255, +0,109,255,227,3,188,5,213,16,6,0,45,0,0,255,255,0,137,0,0,4,201,5,213,16,6,0,46,0,0,255,255,0,215,0,0,4,115,5,213,16,6,0,47,0,0,255,255,0,86,0,0,4,121,5,213,16,6,0,48,0,0,255,255,0,139,0,0,4,70,5,213,16,6,0,49,0,0,255,255,0,117,255,227,4,92,5,240,16, +6,0,50,0,0,255,255,0,197,0,0,4,117,5,213,16,6,0,51,0,0,255,255,0,117,254,242,4,92,5,240,16,6,0,52,0,0,255,255,0,143,0,0,4,209,5,213,16,6,0,53,0,0,255,255,0,139,255,227,4,74,5,240,16,6,0,54,0,0,255,255,0,47,0,0,4,162,5,213,16,6,0,55,0,0,255,255,0,147, +255,227,4,61,5,213,16,6,0,56,0,0,255,255,0,57,0,0,4,152,5,213,16,6,0,57,0,0,255,255,0,0,0,0,4,209,5,213,16,6,0,58,0,0,255,255,0,18,0,0,4,190,5,213,16,6,0,59,0,0,255,255,0,37,0,0,4,172,5,213,16,6,0,60,0,0,255,255,0,156,0,0,4,145,5,213,16,6,0,61,0,0,255, +255,0,133,255,227,4,35,4,123,16,6,0,68,0,0,255,255,0,193,255,227,4,88,6,20,16,6,0,69,0,0,255,255,0,195,255,227,4,37,4,123,16,6,0,70,0,0,255,255,0,123,255,227,4,18,6,20,16,6,0,71,0,0,255,255,0,123,255,227,4,88,4,123,16,6,0,72,0,0,255,255,0,195,0,0,4,39, +6,20,16,6,0,73,0,0,255,255,0,123,254,72,4,18,4,123,16,6,0,74,0,0,255,255,0,195,0,0,4,27,6,20,16,6,0,75,0,0,255,255,0,178,0,0,4,68,6,20,16,6,0,76,0,0,255,255,0,186,254,86,3,16,6,20,16,6,0,77,0,0,255,255,0,236,0,0,4,178,6,20,16,6,0,78,0,0,255,255,0,160, +0,0,4,10,6,31,16,6,0,79,0,0,255,255,0,109,0,0,4,111,4,123,16,6,0,80,0,0,255,255,0,195,0,0,4,27,4,123,16,6,0,81,0,0,255,255,0,137,255,227,4,72,4,123,16,6,0,82,0,0,255,255,0,190,254,86,4,84,4,123,16,6,0,83,0,0,255,255,0,137,254,82,4,31,4,119,16,6,0,84, +0,0,255,255,1,106,0,0,4,131,4,123,16,6,0,85,0,0,255,255,0,213,255,227,4,6,4,123,16,6,0,86,0,0,255,255,0,131,0,0,4,8,5,158,16,6,0,87,0,0,255,255,0,195,255,227,4,27,4,94,16,6,0,88,0,0,255,255,0,100,0,0,4,109,4,96,16,6,0,89,0,0,255,255,0,0,0,0,4,209,4,96, +16,6,0,90,0,0,255,255,0,76,0,0,4,133,4,96,16,6,0,91,0,0,255,255,0,104,254,86,4,129,4,96,16,6,0,92,0,0,255,255,0,203,0,0,4,16,4,98,16,6,0,93,0,0,255,255,0,133,255,227,4,76,5,240,16,6,0,19,0,0,255,255,0,246,0,0,4,70,5,213,16,6,0,20,0,0,255,255,0,152,0, +0,4,35,5,240,16,6,0,21,0,0,255,255,0,137,255,227,4,55,5,240,16,6,0,22,0,0,255,255,0,102,0,0,4,111,5,213,16,6,0,23,0,0,255,255,0,143,255,227,4,45,5,213,16,6,0,24,0,0,255,255,0,133,255,227,4,76,5,240,16,6,0,25,0,0,255,255,0,139,0,0,4,55,5,213,16,6,0,26, +0,0,255,255,0,131,255,227,4,78,5,240,16,6,0,27,0,0,255,255,0,127,255,227,4,70,5,240,16,6,0,28,0,0,0,1,1,219,4,238,2,230,6,102,0,3,0,17,64,6,0,3,4,1,3,4,16,212,204,49,0,16,212,204,48,1,51,3,35,2,32,198,113,154,6,102,254,136,0,2,1,63,5,14,3,145,5,217,0, +3,0,7,0,81,64,13,4,0,222,6,2,8,5,97,4,1,97,0,8,16,212,252,212,236,49,0,16,212,60,236,50,48,0,75,176,14,84,88,189,0,8,0,64,0,1,0,8,0,8,255,192,56,17,55,56,89,1,75,176,14,84,75,176,13,84,91,88,189,0,8,255,192,0,1,0,8,0,8,0,64,56,17,55,56,89,1,51,21,35, +37,51,21,35,1,63,203,203,1,136,202,202,5,217,203,203,203,0,0,0,1,1,219,4,238,3,90,5,246,0,3,0,107,181,0,2,4,1,3,4,16,212,196,49,0,16,212,196,48,0,75,176,12,84,88,189,0,4,255,192,0,1,0,4,0,4,0,64,56,17,55,56,89,0,75,176,14,84,88,189,0,4,0,64,0,1,0,4,0, +4,255,192,56,17,55,56,89,64,38,15,0,15,1,10,2,10,3,31,0,31,1,31,2,31,3,47,0,47,1,47,2,47,3,12,15,0,15,1,31,0,31,1,47,0,47,1,6,93,1,93,1,51,3,35,2,160,186,229,154,5,246,254,248,0,0,0,1,1,31,5,14,3,178,5,233,0,29,0,209,64,30,22,16,15,3,19,12,7,1,0,3,8, +4,204,23,12,19,204,27,8,30,16,1,15,0,7,22,24,7,9,30,16,212,196,212,196,17,57,57,57,57,49,0,16,212,60,252,212,60,236,17,23,57,17,18,23,57,48,0,75,176,14,84,75,176,17,84,91,88,189,0,30,0,64,0,1,0,30,0,30,255,192,56,17,55,56,89,64,116,9,0,9,1,15,11,15,12, +15,13,13,14,15,15,15,16,15,17,15,18,15,19,15,20,15,21,15,22,15,23,15,24,11,25,26,0,26,1,29,11,29,12,29,13,30,14,31,15,31,16,31,17,31,18,31,19,31,20,31,21,31,22,31,23,31,24,33,15,1,15,2,15,3,15,4,15,5,15,11,15,12,15,13,15,21,15,22,15,23,15,24,31,1,31, +2,31,3,31,4,31,5,31,11,31,12,31,13,31,21,31,22,31,23,31,24,24,93,1,93,1,39,46,1,35,34,6,29,1,35,52,54,51,50,22,31,1,30,1,51,50,54,61,1,51,14,1,35,34,38,2,100,57,25,31,12,35,40,125,103,85,36,61,49,57,22,35,15,31,40,125,2,102,84,34,60,5,57,33,14,11,50, +45,6,101,118,16,27,30,13,12,51,41,6,100,119,16,0,1,1,121,4,238,2,246,5,246,0,3,0,105,181,0,1,4,1,3,4,16,212,196,49,0,16,212,196,48,0,75,176,12,84,88,189,0,4,255,192,0,1,0,4,0,4,0,64,56,17,55,56,89,0,75,176,14,84,88,189,0,4,0,64,0,1,0,4,0,4,255,192,56, +17,55,56,89,1,75,176,14,84,88,189,0,4,0,64,0,1,0,4,0,4,255,192,56,17,55,56,89,64,13,15,0,15,3,31,0,31,3,47,0,47,3,6,0,93,1,19,35,3,2,49,197,154,227,5,246,254,248,1,8,0,0,0,1,1,55,4,238,3,154,5,248,0,6,0,93,64,9,4,0,5,2,7,4,2,6,7,16,212,196,57,49,0,16, +212,60,196,57,48,0,75,176,12,84,88,189,0,7,255,192,0,1,0,7,0,7,0,64,56,17,55,56,89,0,75,176,14,84,88,189,0,7,0,64,0,1,0,7,0,7,255,192,56,17,55,56,89,64,19,15,0,15,1,12,4,31,0,31,1,28,4,47,0,47,1,44,4,9,93,1,51,19,35,39,7,35,2,10,189,211,140,166,165,140, +5,248,254,246,178,178,0,1,1,55,4,238,3,154,5,248,0,6,0,105,64,9,3,4,1,0,7,3,5,1,7,16,212,196,57,49,0,16,212,196,50,57,48,0,75,176,14,84,88,189,0,7,0,64,0,1,0,7,0,7,255,192,56,17,55,56,89,0,75,176,12,84,88,189,0,7,255,192,0,1,0,7,0,7,0,64,56,17,55,56, +89,64,31,15,1,15,2,10,3,15,4,15,5,31,1,31,2,26,3,31,4,31,5,47,1,47,2,42,3,47,4,47,5,15,93,1,3,51,23,55,51,3,2,10,211,140,165,166,140,211,4,238,1,10,178,178,254,246,0,0,0,1,0,27,1,248,4,90,3,106,0,3,0,25,64,10,1,0,3,2,4,2,0,3,1,4,16,212,196,57,57,49,0, +16,212,220,212,204,48,19,39,1,23,51,24,4,36,27,1,248,108,1,6,108,0,0,0,1,1,47,6,123,3,162,7,109,0,12,0,0,1,62,1,32,22,23,35,46,1,35,34,6,7,1,47,11,158,1,32,159,11,119,15,97,83,82,100,12,6,123,120,122,123,119,56,55,57,54,0,1,1,47,6,123,3,162,7,109,0,13, +0,31,178,7,0,4,184,1,3,64,9,11,14,7,80,8,1,80,0,14,16,212,236,212,236,49,0,16,212,252,196,50,48,1,51,30,1,51,50,54,55,51,14,1,35,34,38,1,47,119,12,100,82,83,97,15,119,11,159,144,144,158,7,109,54,57,55,56,119,123,122,0,0,1,2,1,6,131,2,206,7,80,0,3,0,18, +183,0,222,2,4,1,97,0,4,16,212,236,49,0,16,212,236,48,1,51,21,35,2,1,205,205,7,80,205,0,0,2,1,88,6,99,4,22,7,107,0,3,0,7,0,25,64,10,0,4,3,7,8,1,3,5,7,8,16,212,204,212,204,49,0,16,212,60,204,50,48,1,51,3,35,3,51,3,35,3,92,186,229,154,122,186,229,154,7, +107,254,248,1,8,254,248,0,0,0,2,0,187,6,99,3,121,7,107,0,3,0,7,0,0,1,19,35,3,33,19,35,3,1,117,197,154,229,1,249,197,154,229,7,107,254,248,1,8,254,248,1,8,0,2,1,102,0,0,3,149,5,240,0,36,0,40,0,0,1,35,53,52,55,54,63,1,62,1,53,52,39,38,39,38,7,6,7,53,54, +55,54,23,22,23,22,21,20,7,6,15,1,6,7,6,21,3,51,21,35,2,174,194,19,20,55,58,41,30,42,37,62,56,39,57,64,66,57,81,91,126,67,71,21,22,61,57,46,12,12,199,203,203,1,145,154,98,69,66,84,89,59,88,49,73,42,37,4,2,22,35,68,217,62,23,34,6,7,89,96,161,76,65,66,92, +86,69,39,42,61,254,195,254,0,0,0,1,1,61,6,156,3,147,7,48,0,3,0,17,182,2,182,0,4,1,0,4,16,212,204,49,0,16,212,236,48,1,33,21,33,1,61,2,86,253,170,7,48,148,0,1,0,156,255,52,4,53,255,166,0,3,0,0,5,33,53,33,4,53,252,103,3,153,204,114,0,0,0,1,0,6,255,52,4, +203,255,166,0,3,0,0,5,33,53,33,4,203,251,59,4,197,204,114,0,0,0,1,1,0,255,52,3,209,255,166,0,3,0,0,5,33,53,33,3,209,253,47,2,209,204,114,0,0,0,2,1,94,1,212,3,115,3,233,0,11,0,19,0,0,1,50,23,30,1,21,20,6,34,38,52,54,22,34,6,20,22,50,54,52,2,104,114,76, +38,39,156,226,151,154,171,118,85,82,121,86,3,233,80,37,96,56,110,154,151,226,156,124,84,121,82,84,118,0,0,0,0,2,1,63,5,70,3,145,6,16,0,3,0,7,0,0,1,51,21,35,37,51,21,35,1,63,203,203,1,136,202,202,6,16,202,202,202,0,0,0,0,1,0,0,0,0,0,150,0,150,0,3,0,0, +53,51,21,35,150,150,150,150,0,0,0,2,0,0,0,0,1,144,0,150,0,3,0,7,0,0,55,51,21,35,39,51,21,35,250,150,150,250,150,150,150,150,150,150,0,0,0,3,0,0,0,0,1,144,1,144,0,3,0,7,0,11,0,0,19,51,21,35,23,51,21,35,39,51,21,35,125,150,150,125,150,150,250,150,150,1, +144,150,100,150,150,150,0,0,0,1,0,69,255,236,4,229,2,28,0,38,0,0,5,34,39,38,53,52,55,51,6,21,20,23,22,51,50,55,54,55,54,53,52,39,51,22,21,20,23,22,59,1,21,35,34,39,38,39,6,7,6,2,31,186,131,157,41,184,43,117,98,127,69,130,87,45,55,29,184,19,24,19,24,33, +75,52,47,43,20,88,96,116,20,56,65,219,62,124,138,48,108,30,25,55,37,53,65,56,62,55,75,90,100,51,40,184,44,42,79,81,47,57,0,0,0,2,255,236,0,0,3,63,3,217,0,15,0,48,0,0,1,54,53,52,39,38,7,6,7,6,7,20,23,22,51,50,1,51,50,55,54,55,54,55,6,7,6,39,38,53,52,55, +54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,33,2,86,41,66,31,44,52,40,40,1,55,40,42,72,253,174,241,84,151,79,60,31,15,63,97,130,78,98,8,23,150,78,76,90,66,96,46,23,78,74,124,109,145,254,191,2,25,43,77,59,51,25,1,1,42,41,51,80,38,25,254,183,23,12,93,48, +50,55,2,2,69,87,129,52,44,148,69,36,50,72,102,51,140,208,143,136,44,39,0,0,0,0,2,255,236,0,0,4,229,3,8,0,32,0,51,0,0,1,22,23,22,21,20,7,6,7,22,59,1,21,33,34,39,6,35,33,53,51,50,55,38,39,38,53,52,55,54,55,54,50,6,34,7,6,7,6,21,20,23,22,23,54,55,54,53, +52,39,38,39,2,200,183,25,8,22,28,36,38,148,225,254,197,136,186,184,136,254,196,226,146,40,30,36,20,8,23,185,30,128,50,28,18,56,24,10,24,30,68,64,36,24,10,24,56,2,250,80,150,50,42,73,49,67,50,17,184,57,57,184,17,40,77,46,76,44,48,143,87,14,184,10,32,53, +21,29,43,53,68,22,21,69,50,46,24,26,52,33,0,2,255,237,254,20,4,229,2,228,0,46,0,64,0,0,37,38,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,23,22,59,1,21,43,1,6,7,6,7,6,39,36,39,38,53,52,55,51,6,21,20,23,22,51,50,55,54,19,54,39,38,39,38,35,34,7,6,7, +6,21,20,23,22,23,22,3,140,66,46,121,57,147,6,40,147,41,87,112,56,99,50,20,6,26,4,88,93,48,30,76,104,142,151,164,254,211,94,69,62,184,62,27,58,195,108,117,158,123,4,22,19,47,34,39,34,21,53,19,10,57,76,100,47,10,5,13,35,43,109,185,61,26,165,69,19,50,88, +145,58,214,1,184,83,109,149,74,78,1,2,190,138,125,166,96,107,155,73,61,130,60,81,1,107,122,87,75,35,25,10,28,57,30,25,60,44,59,20,9,0,0,0,2,255,106,255,165,4,229,3,4,0,43,0,61,0,0,37,6,7,6,7,6,39,36,3,52,55,51,6,21,20,23,22,51,50,55,38,39,38,53,52,55, +54,55,54,51,50,23,22,23,22,21,20,7,22,59,1,21,35,34,39,54,53,52,39,38,39,38,35,34,7,6,7,6,21,20,23,22,3,115,61,118,182,124,139,113,254,218,2,64,184,66,170,71,131,112,151,34,29,82,4,22,188,58,52,82,81,139,16,4,80,9,7,149,154,105,111,104,5,14,52,34,40, +24,22,61,19,6,41,49,36,33,36,56,2,2,40,103,1,8,138,92,94,136,125,69,29,58,27,44,124,108,39,28,155,75,23,50,84,149,37,30,131,106,1,184,223,65,109,20,27,71,39,25,10,25,60,19,18,43,66,78,0,0,0,3,0,0,255,6,1,144,0,150,0,3,0,7,0,11,0,0,23,53,51,21,39,53,51, +21,33,53,51,21,125,150,25,150,254,112,150,250,150,150,250,150,150,150,150,0,0,0,0,2,0,0,255,6,0,150,0,150,0,3,0,7,0,0,21,51,21,35,17,51,21,35,150,150,150,150,100,150,1,144,150,0,0,0,0,4,0,0,255,6,1,144,0,150,0,3,0,7,0,11,0,15,0,0,23,51,21,35,17,51,21, +35,7,51,21,35,17,51,21,35,250,150,150,150,150,250,150,150,150,150,100,150,1,144,150,100,150,1,144,150,0,1,0,0,4,116,2,183,7,56,0,3,0,0,9,1,53,1,2,183,253,73,2,183,6,134,253,238,178,2,18,0,0,1,0,0,4,243,3,156,7,57,0,3,0,0,9,1,53,1,3,156,252,100,3,156, +6,135,254,109,178,1,147,0,0,2,0,0,0,0,1,182,1,183,0,11,0,23,0,0,37,52,39,38,34,6,21,20,23,22,50,62,1,20,7,6,34,39,38,52,55,54,50,23,1,60,28,28,82,56,28,28,82,56,122,63,64,184,63,64,64,63,184,64,220,40,28,29,56,41,42,28,27,56,133,184,64,64,64,64,184,64, +63,63,0,1,0,149,254,86,4,60,5,213,0,19,0,68,64,33,17,1,2,1,2,16,17,16,66,17,2,3,0,180,19,11,151,10,16,19,1,17,16,3,17,11,4,49,17,17,0,48,20,16,252,236,252,196,236,50,17,57,49,0,47,60,212,236,16,236,50,57,57,48,75,83,88,7,16,4,201,7,16,4,201,89,19,51, +1,17,51,17,20,7,6,43,1,53,51,50,55,54,53,1,17,35,149,185,2,53,185,89,90,165,205,185,90,45,44,253,203,185,5,213,251,151,4,105,250,23,195,105,106,156,62,62,146,4,105,251,151,0,0,0,0,1,0,69,255,236,4,176,2,27,0,25,0,0,1,22,21,20,7,6,5,6,39,38,53,52,55,51, +6,21,20,23,22,51,50,55,54,53,52,39,4,150,26,166,152,254,233,223,154,157,41,184,43,117,98,132,188,106,123,25,2,27,71,132,123,121,111,1,1,57,59,225,62,124,138,48,108,30,25,65,76,106,64,71,0,2,0,31,254,125,4,116,3,217,0,15,0,56,0,0,1,54,53,52,39,38,7,6, +7,6,7,20,23,22,51,50,1,54,55,54,17,6,35,34,39,38,53,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,39,38,39,38,53,52,55,51,6,7,20,23,22,3,129,41,66,31,44,52,40,40,1,55,40,42,72,254,91,212,98,203,63,122,133,75,98,8,23,150,78,76,99,57,103,39,33,46,57,165, +187,233,206,138,77,82,183,86,2,18,86,2,25,43,77,59,51,25,1,1,42,41,51,80,38,25,253,59,2,102,212,1,52,75,67,87,129,45,51,148,69,36,50,90,119,102,160,252,142,179,131,148,1,1,191,106,125,180,216,187,153,72,40,176,0,0,255,255,0,69,254,12,4,176,3,32,16,39, +13,30,1,152,254,12,16,38,13,32,0,0,16,7,13,18,1,184,2,138,255,255,0,69,255,236,4,176,3,182,16,39,13,25,1,169,3,32,16,6,13,32,0,0,255,255,0,88,254,12,4,173,5,175,16,39,4,133,255,174,255,56,16,6,4,99,0,0,255,255,0,88,254,12,4,173,5,170,16,39,13,26,1,194, +5,20,16,6,4,99,0,0,255,255,0,88,254,12,4,173,5,170,16,39,13,19,1,84,4,26,16,6,4,99,0,0,255,255,255,204,254,8,4,181,4,6,16,38,4,103,0,0,16,7,4,135,1,62,253,210,0,2,255,182,255,164,4,140,3,120,0,14,0,57,0,0,1,54,53,52,39,38,7,34,6,7,20,23,22,51,50,19,6, +7,6,35,34,39,38,3,38,55,51,6,21,20,23,22,51,50,55,54,55,54,55,6,35,34,39,38,53,52,55,54,55,54,51,50,23,22,23,22,21,16,3,163,41,66,31,44,52,80,1,55,38,44,72,157,105,167,178,165,163,114,244,2,2,36,184,36,120,90,131,127,84,188,48,65,38,63,122,133,75,98, +8,23,150,78,76,90,66,96,46,23,1,184,44,76,57,53,26,2,84,50,82,36,26,254,166,84,38,40,41,88,1,21,138,92,94,136,147,45,34,22,50,28,40,104,76,68,86,130,44,52,148,68,36,50,72,102,51,139,254,187,0,0,255,255,0,67,254,200,4,250,7,196,16,39,4,135,1,132,1,144, +16,6,4,117,0,0,0,1,0,54,254,181,4,141,2,176,0,29,0,0,1,20,7,6,7,6,35,34,39,38,17,52,55,51,6,21,20,23,22,51,50,55,54,55,54,53,52,39,51,22,4,141,100,71,142,140,129,172,123,234,53,184,55,161,57,129,84,63,157,58,34,70,184,72,0,255,187,164,116,60,59,63,120, +1,18,174,142,174,142,180,67,24,20,51,167,98,96,249,152,159,0,0,255,255,0,76,254,12,4,51,4,72,16,39,4,135,0,112,254,20,16,6,4,121,0,0,255,255,0,25,254,243,4,209,4,20,16,39,4,135,255,40,253,224,16,6,4,122,0,0,255,255,0,222,255,198,3,243,2,222,16,6,4,120, +0,0,0,2,2,4,0,0,2,207,5,213,0,3,0,9,0,30,64,14,6,0,134,1,136,4,7,6,8,2,3,4,0,10,16,212,60,236,50,57,57,49,0,47,244,252,204,48,1,53,51,21,3,17,19,51,19,17,2,4,203,203,21,161,21,4,215,254,254,251,41,2,143,1,101,254,155,253,113,0,0,0,0,2,0,193,255,229,3, +221,5,213,0,33,0,37,0,130,64,71,11,10,9,8,7,5,12,6,37,25,26,25,3,4,2,2,5,37,26,26,25,66,33,26,5,2,4,6,25,0,16,139,15,141,12,0,34,134,36,12,151,19,153,36,136,38,6,35,25,22,9,31,5,0,3,29,1,26,35,9,41,22,15,29,3,1,15,34,30,35,38,16,212,252,196,212,236,16, +214,238,17,57,17,18,23,57,17,18,57,18,57,49,0,16,228,244,236,16,254,205,16,244,238,18,57,57,23,57,48,75,83,88,7,16,4,237,17,23,57,7,16,4,237,17,23,57,89,34,1,51,21,20,6,15,1,14,1,21,20,22,51,50,54,55,21,14,1,35,34,38,53,52,54,63,1,62,1,53,52,53,54,53, +19,35,53,51,2,37,190,61,84,90,62,47,131,109,78,178,98,94,191,104,186,221,67,94,88,67,38,2,196,202,202,4,68,154,98,137,82,89,59,88,49,89,110,69,68,188,57,56,192,161,76,131,92,86,64,84,63,1,4,23,19,1,14,254,255,255,0,193,255,229,3,221,5,213,18,7,11,181, +0,0,1,117,0,0,0,1,0,0,0,2,94,184,23,224,84,113,95,15,60,245,0,31,8,0,0,0,0,0,211,194,43,248,0,0,0,0,211,194,43,248,251,138,253,1,5,190,8,57,0,0,0,8,0,0,0,1,0,0,0,0,0,1,0,0,7,109,254,29,0,0,4,209,251,138,255,20,5,190,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +4,4,209,0,104,0,0,0,0,4,209,0,0,4,209,0,0,2,4,1,82,0,2,0,190,0,33,0,57,2,16,1,170,1,92,0,166,0,88,1,147,1,100,1,233,0,102,0,133,0,246,0,152,0,137,0,102,0,143,0,133,0,139,0,131,0,127,1,233,1,147,0,88,0,88,0,88,0,244,0,27,0,37,0,166,0,139,0,137,0,197,0, +233,0,102,0,137,0,201,0,109,0,137,0,215,0,86,0,139,0,117,0,197,0,117,0,143,0,139,0,47,0,147,0,57,0,0,0,18,0,37,0,156,1,207,0,102,1,90,0,72,0,0,1,23,0,133,0,193,0,195,0,123,0,123,0,195,0,123,0,195,0,178,0,186,0,236,0,160,0,109,0,195,0,137,0,190,0,137, +1,106,0,213,0,131,0,195,0,100,0,0,0,76,0,104,0,203,0,221,2,18,0,221,0,88,0,0,2,4,0,213,0,139,0,205,0,37,2,18,0,199,1,63,0,0,1,14,0,119,0,88,1,100,0,0,1,61,1,43,0,88,1,66,1,70,1,219,0,195,0,106,1,233,1,139,1,88,0,244,0,193,0,27,0,27,0,27,0,193,0,37,0, +37,0,37,0,37,0,37,0,37,0,0,0,139,0,197,0,197,0,197,0,197,0,201,0,201,0,201,0,201,0,8,0,139,0,117,0,117,0,117,0,117,0,117,0,150,0,8,0,147,0,147,0,147,0,147,0,37,0,201,0,188,0,133,0,133,0,133,0,133,0,133,0,133,0,41,0,195,0,123,0,123,0,123,0,123,0,178,0, +178,0,178,0,178,0,137,0,195,0,137,0,137,0,137,0,137,0,137,0,88,0,47,0,195,0,195,0,195,0,195,0,104,0,190,0,104,0,37,0,133,0,37,0,133,0,37,0,133,0,139,0,195,0,139,0,195,0,139,0,195,0,139,0,195,0,137,0,123,0,8,0,123,0,197,0,123,0,197,0,123,0,197,0,123,0, +197,0,123,0,197,0,123,0,102,0,123,0,102,0,123,0,102,0,123,0,102,0,123,0,137,0,195,0,3,0,70,0,201,0,178,0,201,0,178,0,201,0,178,0,201,0,178,0,201,0,178,255,255,255,252,0,109,0,186,0,137,0,236,0,236,0,200,0,160,0,215,0,160,0,215,0,160,0,215,0,160,255,246, +0,76,0,139,0,195,0,139,0,195,0,139,0,195,0,24,0,147,0,195,0,117,0,137,0,117,0,137,0,117,0,137,0,72,0,14,0,143,1,106,0,143,1,32,0,143,1,106,0,139,0,213,0,139,0,213,0,139,0,213,0,139,0,213,0,47,0,131,0,47,0,131,0,47,0,131,0,147,0,195,0,147,0,195,0,147, +0,195,0,147,0,195,0,147,0,195,0,147,0,195,0,0,0,0,0,37,0,104,0,37,0,156,0,203,0,156,0,203,0,156,0,203,0,195,0,70,0,20,0,166,0,193,0,48,0,60,0,139,0,60,0,94,0,8,0,8,0,131,0,157,0,136,0,197,0,117,0,137,0,63,0,195,0,52,0,28,0,65,0,201,0,201,0,110,0,236, +0,160,0,49,0,109,0,29,0,195,0,117,0,6,0,32,0,45,0,86,0,56,0,190,0,143,0,139,0,213,0,120,0,118,0,131,0,47,0,131,0,47,0,9,0,39,0,74,0,154,0,17,0,24,0,156,0,156,0,26,0,26,0,125,0,173,0,152,0,26,0,125,0,194,0,125,2,3,1,57,0,164,2,3,0,37,0,133,0,201,0,178, +0,117,0,137,0,147,0,195,0,147,0,195,0,147,0,195,0,147,0,195,0,147,0,195,0,122,0,37,0,133,0,37,0,133,0,0,0,41,0,102,0,123,0,137,0,236,0,117,0,137,0,117,0,137,0,26,0,125,0,186,0,102,0,123,0,61,0,139,0,195,0,0,0,41,0,8,0,47,0,37,0,133,0,37,0,133,0,187,0, +123,0,197,0,123,0,187,0,178,0,201,0,178,0,117,0,137,0,117,0,137,0,137,1,104,0,143,1,106,0,147,0,195,0,147,0,195,0,139,0,213,0,47,0,131,0,125,0,174,0,137,0,195,0,147,0,18,0,156,0,203,0,37,0,133,0,197,0,123,0,117,0,137,0,117,0,137,0,117,0,137,0,117,0,137, +0,37,0,104,0,160,0,106,0,131,0,186,0,120,0,120,0,8,0,8,0,47,0,21,0,33,0,213,0,203,0,55,0,8,0,21,0,57,0,21,0,142,0,154,0,123,0,192,0,193,0,184,0,195,0,123,0,123,0,122,0,122,0,30,0,169,0,169,0,56,0,176,0,186,0,123,0,157,0,122,0,102,0,102,0,188,0,195,0, +195,0,142,0,198,0,160,0,88,0,157,0,160,0,40,0,104,0,104,0,103,0,178,0,136,0,144,0,137,0,69,0,170,0,137,0,152,0,152,0,102,1,106,1,106,0,160,0,160,0,122,0,122,0,188,0,125,0,125,0,125,0,118,0,166,0,131,0,0,0,95,0,65,0,72,0,15,0,72,0,102,0,194,0,167,0,125, +0,105,0,194,0,194,0,194,0,194,0,95,0,209,0,176,0,54,0,144,0,202,0,119,0,245,0,35,0,194,0,194,0,29,0,27,0,54,0,153,0,153,0,181,0,135,0,230,0,219,0,143,0,143,0,178,0,197,1,65,1,65,1,230,1,153,1,153,1,81,1,48,0,143,1,17,1,236,1,207,1,207,1,240,1,223,1,223, +1,94,1,94,1,41,1,41,2,36,1,61,2,36,1,61,1,121,1,121,1,182,1,182,1,223,1,223,1,62,1,136,1,47,2,1,1,86,1,164,1,31,1,88,254,161,1,37,1,86,1,91,1,18,1,94,1,44,1,44,1,44,1,44,1,44,0,211,1,141,1,23,1,219,1,41,1,31,1,61,0,0,1,47,2,1,1,63,1,153,1,86,1,88,1,41, +2,34,1,86,0,210,1,47,1,47,1,213,1,239,1,240,1,219,1,121,1,121,1,156,1,204,1,115,1,163,1,250,1,98,1,94,1,95,1,115,1,246,0,182,2,1,1,63,1,141,1,152,1,139,1,174,2,36,1,85,0,206,1,41,1,41,1,47,1,47,1,31,1,61,0,0,0,0,0,88,0,141,0,0,0,47,0,8,1,250,1,85,1,85, +0,206,1,139,1,219,0,0,1,239,4,2,255,20,1,236,1,230,0,139,0,195,2,30,0,184,0,195,0,184,1,147,0,109,1,219,1,63,0,25,1,233,255,31,254,237,255,31,255,181,254,112,255,206,1,54,0,37,0,166,0,215,0,37,0,197,0,156,0,137,0,117,0,201,0,137,0,37,0,86,0,139,0,137, +0,117,0,137,0,197,0,120,0,47,0,37,0,117,0,18,0,117,0,74,0,201,0,37,0,70,0,169,0,195,1,54,0,51,0,70,0,151,0,32,0,137,0,169,0,153,0,195,0,137,1,54,0,236,0,68,0,195,0,116,0,162,0,137,0,80,0,190,0,195,0,137,0,159,0,51,0,76,0,89,0,131,0,70,1,54,0,51,0,137, +0,51,0,70,0,150,0,116,0,34,254,112,0,34,0,109,0,57,0,52,0,117,0,137,0,139,0,155,0,233,0,0,0,96,0,132,0,33,0,89,0,52,0,190,0,195,0,186,0,117,0,162,0,162,0,201,0,190,0,139,0,86,0,127,0,85,0,139,0,139,0,139,0,197,0,197,255,190,0,215,0,139,0,139,0,201,0, +201,0,109,255,237,0,34,255,190,0,137,0,139,0,104,0,137,0,37,0,166,0,166,0,215,0,33,0,197,0,15,0,137,0,139,0,139,0,137,0,4,0,86,0,137,0,117,0,137,0,197,0,139,0,47,0,104,0,66,0,18,0,80,0,137,0,114,0,60,0,32,0,65,0,197,0,139,0,60,0,76,0,133,0,125,0,209, +1,1,0,105,0,123,0,59,0,169,0,195,0,195,0,236,0,30,0,61,0,195,0,137,0,195,0,190,0,195,0,225,0,104,0,99,0,76,0,124,0,195,0,125,0,80,0,30,0,104,0,195,0,195,0,78,0,168,0,123,0,123,0,35,1,1,0,195,0,213,0,178,0,178,0,186,0,10,0,65,0,35,0,236,0,195,0,104,0, +195,0,32,0,30,0,117,0,137,0,215,1,1,0,85,0,127,0,215,1,1,0,15,0,59,0,137,0,169,0,137,0,236,0,31,0,98,0,113,0,125,0,139,0,195,0,47,0,225,0,37,0,92,0,37,0,92,0,18,0,76,0,140,0,195,0,201,0,15,0,59,0,137,0,236,0,137,0,195,0,140,0,195,1,199,0,37,0,133,0,37, +0,133,0,0,0,41,0,197,0,123,0,117,0,122,0,117,0,122,0,15,0,59,0,137,0,169,0,26,0,125,0,139,0,195,0,139,0,195,0,117,0,137,0,117,0,137,0,117,0,137,0,139,0,195,0,104,0,104,0,104,0,104,0,104,0,104,0,137,0,195,0,215,1,1,0,65,0,104,0,137,0,169,0,117,0,137,0, +0,0,0,0,119,0,128,0,85,0,54,0,128,0,96,0,120,0,128,0,43,0,85,0,147,0,154,0,93,0,54,0,147,0,91,0,95,0,54,0,86,0,54,0,64,0,54,0,96,0,147,0,96,0,65,0,96,0,54,0,147,0,33,0,105,0,147,0,64,0,135,0,70,0,51,0,117,0,71,1,223,1,214,1,122,0,225,1,121,0,178,0,188, +0,103,0,183,0,73,0,114,0,164,0,73,0,207,0,183,0,66,0,73,0,188,1,71,0,104,0,137,0,188,0,189,0,171,0,114,0,159,0,104,1,61,0,104,0,173,0,189,0,242,0,103,0,168,0,132,0,189,0,102,0,104,0,188,0,157,0,249,0,104,0,87,0,137,0,40,0,72,1,255,1,100,0,49,0,49,0,90, +0,0,1,214,1,100,1,214,0,218,1,178,1,0,1,189,0,76,1,189,0,25,2,12,0,69,0,222,0,69,0,69,0,88,0,88,0,88,0,232,0,232,255,204,255,204,255,36,255,36,255,16,255,16,0,10,0,10,0,122,0,122,255,236,255,182,0,31,0,8,0,67,0,130,0,54,0,222,0,76,0,25,0,25,1,68,1,68, +1,68,1,68,1,68,1,68,1,48,1,86,1,0,1,189,1,189,1,92,1,250,1,150,0,154,0,134,0,236,0,202,0,154,0,126,0,126,0,162,0,200,1,54,1,214,0,146,1,189,0,69,0,69,0,69,0,69,0,69,0,69,0,88,0,88,0,88,0,88,255,204,255,204,255,182,0,10,0,10,0,0,0,25,1,250,1,150,0,154, +0,134,0,175,0,172,1,8,0,126,0,126,0,162,0,184,0,62,0,108,0,121,0,246,0,124,0,97,0,115,0,123,0,149,0,26,0,106,0,75,0,125,0,125,0,99,0,99,0,101,0,101,0,16,0,115,0,100,0,97,0,111,0,98,0,20,0,119,0,85,0,48,0,91,251,138,0,157,252,198,0,83,0,83,0,83,0,83,1, +207,1,120,0,69,255,240,2,14,0,86,0,95,1,73,255,240,1,150,0,160,0,158,0,110,0,55,0,160,0,158,0,158,0,55,0,160,0,158,0,160,0,158,0,159,0,55,0,160,0,159,0,55,0,159,0,45,0,55,0,55,0,160,0,55,0,158,0,55,0,158,0,86,0,158,0,161,0,160,0,159,0,159,0,158,0,118, +0,160,0,159,0,159,0,139,0,55,0,107,0,161,0,110,0,160,1,35,1,149,0,41,0,169,0,178,0,14,0,137,0,136,0,43,0,63,0,43,0,252,0,245,1,55,1,55,1,76,1,76,1,44,1,58,1,100,1,94,1,18,1,69,1,27,1,60,1,60,1,46,1,63,1,17,1,2,1,65,0,228,1,69,1,69,1,71,0,251,1,71,1,71, +1,49,1,49,1,79,1,79,1,71,1,73,1,56,1,37,1,91,1,58,1,88,1,58,1,58,1,71,1,77,1,91,0,255,1,37,1,35,1,72,1,153,1,91,1,35,0,123,1,58,0,156,0,160,1,71,1,88,1,81,1,58,1,79,1,87,1,98,1,71,1,91,1,67,1,97,1,73,1,71,1,100,1,85,1,85,1,126,1,37,1,37,1,85,1,85,1,63, +1,58,1,58,1,91,1,120,1,77,0,208,1,32,1,70,1,17,1,97,1,94,1,77,1,51,1,58,0,37,0,133,0,166,0,193,0,166,0,193,0,166,0,193,0,139,0,195,0,137,0,123,0,137,0,123,0,137,0,123,0,125,0,123,0,137,0,123,0,197,0,123,0,197,0,123,0,197,0,123,0,233,0,195,0,102,0,123, +0,137,0,195,0,137,0,195,0,137,0,195,0,20,0,55,0,137,0,195,0,201,0,178,0,137,0,236,0,137,0,236,0,137,0,236,0,215,0,160,0,215,0,160,0,215,0,160,0,215,0,160,0,86,0,109,0,86,0,109,0,86,0,109,0,139,0,195,0,139,0,195,0,139,0,195,0,139,0,195,0,117,0,137,0,197, +0,190,0,197,0,190,0,143,1,106,0,143,1,106,0,143,1,61,0,143,1,61,0,139,0,213,0,139,0,213,0,139,0,213,0,47,0,131,0,47,0,131,0,47,0,131,0,47,0,131,0,147,0,195,0,147,0,195,0,147,0,195,0,147,0,195,0,57,0,100,0,57,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,18,0,76,0,18,0,76,0,37,0,104,0,156,0,203,0,156,0,203,0,156,0,203,0,195,0,131,0,0,0,104,0,195,0,137,0,37,0,133,0,37,0,133,0,37,0,133,0,37,0,133,0,197,0,123,0,197,0,123,0,197,0,123,0,201,0,178,0,117,0,137,0,117,0,137,0,6,0,32,0,6,0,32,0,6,0,32,0, +6,0,32,0,147,0,195,0,9,0,39,0,9,0,39,0,9,0,39,0,9,0,39,0,37,0,104,0,37,0,104,0,37,0,104,0,70,0,70,0,70,0,70,0,70,0,70,0,70,0,70,0,37,0,37,254,108,254,108,255,27,255,7,255,193,255,143,0,169,0,169,0,169,0,169,0,169,0,169,255,127,255,127,253,139,253,139, +254,8,253,244,0,195,0,195,0,195,0,195,0,195,0,195,0,195,0,195,255,77,255,77,253,64,253,64,253,164,253,144,254,99,254,99,1,54,1,54,0,245,0,245,1,39,1,19,1,31,1,31,255,127,255,127,253,164,253,164,254,8,253,244,254,174,254,174,0,137,0,137,0,137,0,137,0, +137,0,137,255,202,255,127,253,139,253,139,254,158,254,138,0,51,0,51,0,51,0,51,0,51,0,51,0,51,0,51,254,233,253,64,253,69,254,24,0,70,0,70,0,70,0,70,0,70,0,70,0,70,0,70,255,202,255,102,253,139,253,139,254,183,254,163,254,249,254,174,0,70,0,70,0,169,0,169, +0,195,0,195,1,23,1,54,0,137,0,137,0,51,0,51,0,70,0,70,0,70,0,70,0,70,0,70,0,70,0,70,0,70,0,70,0,37,0,37,254,108,254,108,255,27,255,7,255,193,255,143,0,195,0,195,0,195,0,195,0,195,0,195,0,195,0,195,255,77,255,77,253,64,253,64,253,164,253,144,254,99,254, +99,0,70,0,70,0,70,0,70,0,70,0,70,0,70,0,70,255,202,255,102,253,139,253,139,254,183,254,163,254,249,254,174,0,70,0,70,0,70,0,70,0,70,0,70,0,70,0,37,0,37,255,135,0,25,0,37,1,239,2,30,1,239,1,31,1,31,0,195,0,195,0,195,0,195,0,195,254,141,255,31,254,91,254, +237,0,137,0,245,1,39,1,31,1,47,1,54,1,23,1,54,1,31,1,31,0,201,0,201,254,191,255,31,0,245,1,19,1,31,0,51,0,51,0,51,0,51,0,190,0,190,0,51,0,51,0,37,0,37,254,91,254,112,255,127,1,23,1,63,1,23,0,70,0,70,0,70,0,70,0,70,254,166,255,181,254,166,255,206,0,74, +1,219,1,239,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,100,1,100,0,0,0,0,0,0,0,0,1,29,0,0,1,207,1,207,1,147,1,207,0,211,0,211,0,211,0,211,0,162,0,162,1,63,1,63,0,80,0,0,0,0,0,0,1,172,1,22,0,128,1,172,1,22,0,128,1,90,1,164,0,208,0,244,0,0,255,188,1, +207,1,90,0,33,0,33,0,208,0,203,0,0,1,61,1,72,1,12,1,63,1,73,1,61,1,59,1,48,1,28,1,28,1,28,1,216,1,216,1,65,1,61,1,88,1,66,1,70,1,12,1,63,1,73,1,61,1,59,1,48,1,28,1,28,1,28,1,216,1,216,1,69,1,49,1,58,1,18,1,49,1,65,1,56,1,86,1,37,1,65,1,71,1,91,1,77,0, +10,0,123,0,95,0,0,0,139,0,109,0,0,0,10,0,10,0,0,0,42,0,123,0,37,0,42,0,47,0,30,0,46,0,106,0,53,0,39,0,0,0,130,0,47,0,104,0,10,0,102,0,140,0,6,0,58,0,84,0,84,0,74,0,10,0,0,0,66,0,17,0,37,0,0,0,48,0,74,0,137,0,37,0,11,0,27,0,27,0,27,0,27,0,27,0,27,0,27, +0,27,0,10,0,27,0,27,0,27,0,27,0,27,0,27,0,27,0,27,0,66,1,28,0,66,1,28,0,66,1,28,0,184,0,184,0,184,0,184,0,66,0,66,0,89,0,89,0,66,1,28,0,66,1,28,0,66,0,66,0,66,1,28,0,66,1,28,1,28,0,66,0,66,0,66,0,66,0,66,0,66,0,113,0,183,0,183,0,183,0,183,0,186,0,63, +0,81,0,81,0,50,0,66,0,88,0,88,0,66,0,66,2,22,1,28,0,66,0,66,2,22,1,71,0,66,0,42,0,66,0,66,0,42,0,66,0,42,0,66,0,66,0,66,0,66,0,66,0,66,1,28,0,66,1,28,0,66,1,28,0,155,0,155,0,155,0,155,0,66,0,66,0,66,0,66,1,28,1,28,0,66,1,28,0,66,1,28,0,66,0,66,0,25,0, +243,0,66,0,243,0,243,0,243,0,243,0,243,0,243,0,243,0,66,0,69,0,69,0,243,0,66,0,42,0,66,0,66,0,66,0,66,0,66,0,66,0,66,0,25,0,66,0,25,0,37,0,117,0,182,0,178,0,178,0,73,255,250,255,250,0,129,0,129,0,130,0,129,0,129,0,130,0,250,0,152,0,152,0,143,0,88,0,88, +0,102,0,166,1,43,1,63,0,59,0,59,0,59,0,186,0,41,0,125,0,125,2,18,0,164,0,164,0,164,0,164,0,129,0,63,0,53,0,187,0,188,1,232,0,187,0,88,0,74,0,87,0,88,0,88,0,88,0,88,0,88,0,88,0,88,0,88,0,88,0,88,0,88,0,88,0,88,0,88,0,88,0,87,0,88,0,88,0,88,0,88,0,88,0, +87,0,74,0,74,0,88,0,88,0,88,0,88,0,88,0,88,0,88,0,69,0,88,0,88,0,88,0,88,0,88,0,88,0,88,0,88,0,86,0,86,0,86,0,86,0,87,0,88,0,88,0,88,0,88,0,86,0,86,0,86,0,86,0,86,0,86,0,86,0,86,0,86,0,88,0,86,0,86,0,86,0,86,0,86,0,86,0,88,0,88,0,88,0,88,0,88,0,88,0, +88,0,88,0,88,0,88,0,131,0,131,0,88,0,88,0,88,0,88,0,94,0,94,0,79,0,79,0,79,0,79,0,79,0,79,0,79,0,79,0,79,0,80,0,80,0,80,0,80,0,88,0,88,0,88,0,88,0,88,0,88,0,88,0,88,0,28,0,131,0,131,0,105,1,233,1,8,0,88,255,248,255,248,0,90,0,90,0,88,0,88,0,86,0,88,0, +86,0,86,0,86,0,86,0,88,0,88,0,88,0,88,0,86,0,86,0,86,0,86,0,80,0,73,0,114,0,146,0,146,0,146,0,146,0,146,1,207,1,90,1,207,1,90,2,37,0,13,2,37,0,13,0,88,0,97,0,6,0,6,0,184,0,166,0,71,0,88,1,43,1,28,1,43,1,28,2,1,0,124,0,104,0,6,0,125,0,50,0,6,0,72,0,88, +1,0,0,6,0,6,0,6,0,6,0,6,0,6,0,6,0,88,0,88,0,6,0,6,0,6,0,6,0,66,0,66,0,6,0,6,0,6,0,88,0,37,0,6,0,6,0,88,0,88,0,6,0,88,0,37,0,6,0,6,0,88,0,88,0,6,1,0,0,6,0,6,1,0,0,6,0,164,0,6,255,236,0,6,0,88,0,0,1,8,1,63,0,6,0,164,0,88,0,88,0,88,0,88,0,37,0,88,0,88,1, +0,0,6,0,6,0,88,0,88,1,54,0,190,0,70,0,6,0,156,1,0,0,6,0,70,0,26,0,72,0,6,0,6,0,6,0,82,0,70,0,70,0,70,0,6,1,24,1,24,1,24,1,25,2,246,1,25,1,24,1,24,1,24,1,24,2,245,1,24,2,12,0,17,2,12,2,12,0,16,2,11,0,16,2,1,0,25,0,6,0,150,255,236,255,236,2,24,1,200,0, +60,0,60,2,24,1,200,0,60,0,60,2,24,1,200,2,24,2,24,1,200,1,200,255,236,255,236,255,236,255,236,2,24,2,24,1,200,1,200,255,236,255,236,255,236,255,236,2,24,2,24,1,200,1,200,1,200,1,200,1,200,1,200,255,236,255,236,255,236,255,236,255,236,255,236,255,236, +255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255, +236,255,236,0,60,0,60,2,24,1,200,255,236,1,120,2,24,1,120,1,120,255,236,255,236,255,236,2,24,1,120,1,120,255,236,255,236,255,236,2,24,1,120,1,120,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,2,24,255, +236,255,236,2,24,255,167,255,167,255,167,255,236,2,24,2,104,2,24,255,236,1,200,2,104,1,200,255,236,1,200,255,236,1,200,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,255,236,2,105, +0,0,0,0,0,0,255,236,4,70,255,236,2,105,255,236,255,236,255,236,255,236,255,236,2,105,255,236,255,236,0,6,0,6,0,6,0,6,0,6,0,6,0,6,0,6,0,6,0,6,0,219,0,219,0,6,0,6,1,68,1,68,0,6,0,6,0,6,0,6,0,219,0,219,0,6,0,6,0,219,0,219,0,6,0,6,0,6,0,6,0,219,0,219,0,6, +0,6,0,219,0,219,0,6,0,6,0,6,0,6,0,6,0,6,0,117,0,6,0,6,0,6,0,6,0,6,0,6,0,6,0,6,0,6,0,6,0,6,1,55,1,55,255,236,255,236,255,236,255,236,1,55,1,55,1,55,1,55,0,6,0,6,0,6,0,6,0,6,0,6,1,63,0,6,0,6,0,6,0,6,0,6,0,6,0,6,0,6,255,236,0,6,0,6,0,6,0,6,0,6,0,6,0,6,0, +6,0,6,0,6,0,6,0,97,0,97,0,175,0,175,0,6,0,34,0,50,0,34,0,89,0,29,0,58,0,58,0,200,0,59,0,43,0,15,0,18,0,54,0,46,0,20,0,8,0,111,0,99,0,133,0,201,0,28,0,78,0,56,0,47,0,38,0,47,0,47,0,47,0,14,0,140,0,14,0,140,0,12,0,9,0,8,0,34,0,78,0,96,0,121,0,97,0,204, +0,55,0,30,0,8,0,103,0,15,0,27,0,14,0,27,0,33,0,33,0,33,0,33,0,156,0,149,0,189,0,145,0,145,0,21,0,71,0,174,0,67,0,76,0,215,0,24,0,53,0,27,0,52,0,61,0,47,0,85,0,50,0,56,0,21,0,89,0,94,0,67,0,86,0,112,0,222,0,144,0,156,0,106,0,54,0,148,0,226,0,103,0,118, +0,128,0,14,0,145,0,50,0,127,0,11,0,145,0,49,0,46,1,114,0,162,0,106,0,17,1,68,1,177,1,55,0,96,0,46,0,47,0,60,0,75,0,68,0,36,0,62,0,75,0,45,0,45,0,57,0,46,0,55,0,46,0,80,0,60,0,60,0,60,0,60,0,60,0,60,0,46,0,46,0,46,0,46,0,82,0,82,0,150,0,115,0,39,0,31, +0,129,0,188,0,19,0,22,0,74,0,30,0,42,0,82,0,42,0,34,0,136,0,243,0,222,0,46,0,46,0,58,0,61,0,52,0,37,0,61,0,63,1,68,0,45,0,87,0,38,0,87,0,59,0,37,0,152,0,74,0,129,0,64,0,131,0,51,0,64,0,86,0,57,0,48,0,155,0,126,0,144,0,48,0,71,0,31,0,28,0,26,0,23,0,43, +0,37,0,40,0,67,0,40,0,35,0,40,0,61,0,40,0,46,0,54,0,87,0,48,0,36,0,26,0,50,0,31,0,26,0,36,0,48,0,49,0,55,0,52,0,33,0,36,0,22,0,22,0,37,0,50,0,32,0,48,0,25,0,50,0,41,0,33,0,23,0,34,0,36,0,69,0,61,0,56,0,48,0,43,2,27,1,205,1,81,1,221,1,211,1,0,0,246,0, +103,0,255,0,190,0,46,0,114,0,65,0,49,0,240,0,240,1,102,1,110,1,67,1,68,0,210,0,210,0,205,0,206,1,201,1,201,1,25,0,249,0,83,0,116,0,83,0,116,0,45,0,73,0,83,0,45,0,54,0,83,0,83,0,96,0,123,0,123,0,54,0,54,1,79,0,54,0,101,0,101,0,53,0,97,0,125,0,84,0,50, +0,41,0,145,0,88,0,116,0,83,0,117,0,78,0,42,0,117,0,53,0,29,0,38,0,37,0,50,0,88,1,56,1,55,0,28,0,117,1,41,1,40,1,134,1,134,0,190,0,190,255,156,255,156,255,156,1,44,1,44,1,144,0,250,0,117,0,88,0,88,0,80,0,150,0,88,0,88,0,84,1,49,1,49,0,139,0,240,0,240, +0,139,0,84,1,49,0,6,0,6,0,6,0,6,0,6,0,6,0,6,0,6,0,6,0,143,0,106,0,86,0,37,0,106,0,137,0,195,0,76,0,152,0,137,1,230,1,8,0,139,0,156,0,193,0,88,1,207,1,90,1,207,1,90,0,218,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,84, +1,84,2,40,2,40,2,40,1,65,1,110,0,235,0,235,0,137,0,195,1,233,1,136,2,4,2,16,0,137,0,157,0,84,0,122,0,20,0,230,0,63,0,137,0,35,0,35,0,69,0,69,255,236,255,236,0,69,0,69,255,236,255,236,0,69,0,69,255,236,255,236,0,69,0,69,255,236,255,236,0,69,0,69,255,236, +255,236,0,69,0,69,255,236,255,236,255,182,255,106,255,236,255,236,255,182,255,106,255,236,255,236,0,88,0,88,255,236,255,236,0,88,0,88,255,236,255,236,0,88,0,88,255,236,255,236,0,88,0,88,255,236,255,236,255,204,255,96,255,204,255,96,0,10,255,131,255,236, +255,236,0,10,255,131,255,236,255,236,0,54,255,213,0,0,0,0,255,236,255,236,255,236,255,236,0,25,255,124,255,236,255,236,1,68,255,236,1,68,3,34,1,68,1,68,255,236,1,68,255,236,1,68,255,236,1,48,255,236,1,86,255,236,1,178,1,0,1,0,1,179,1,228,0,76,0,90,1, +182,2,19,0,25,255,124,255,236,255,236,2,12,2,76,0,69,0,69,255,236,255,236,0,222,0,242,0,69,0,69,255,236,255,236,0,69,0,69,255,236,255,236,0,88,0,88,255,236,255,236,0,88,0,88,255,236,255,236,0,88,0,88,255,236,255,236,0,232,0,232,0,232,0,232,255,204,255, +96,255,204,255,96,255,36,254,216,255,236,255,236,255,36,254,216,255,236,255,236,255,16,254,197,255,236,255,236,255,16,254,197,255,236,255,236,0,10,0,20,255,236,255,236,0,10,0,20,255,236,255,236,0,122,0,148,255,236,255,236,0,122,0,148,255,236,255,236, +255,182,255,106,255,236,255,236,0,31,255,237,255,236,255,236,0,8,255,161,255,236,255,236,0,67,0,10,255,236,255,236,0,130,0,71,255,236,255,236,0,54,255,213,255,236,255,236,0,222,0,242,255,236,255,236,0,76,0,90,0,25,255,124,0,25,255,124,255,236,255,236, +255,150,255,64,0,83,255,224,0,133,0,95,0,179,0,95,0,0,0,0,0,0,0,0,0,0,0,82,0,178,0,37,0,166,0,139,0,137,0,197,0,233,0,102,0,137,0,201,0,109,0,137,0,215,0,86,0,139,0,117,0,197,0,117,0,143,0,139,0,47,0,147,0,57,0,0,0,18,0,37,0,156,0,133,0,193,0,195,0,123, +0,123,0,195,0,123,0,195,0,178,0,186,0,236,0,160,0,109,0,195,0,137,0,190,0,137,1,106,0,213,0,131,0,195,0,100,0,0,0,76,0,104,0,203,0,133,0,246,0,152,0,137,0,102,0,143,0,133,0,139,0,131,0,127,1,219,1,63,1,219,1,31,1,121,1,55,1,55,0,27,1,47,1,47,2,1,1,88, +0,187,1,102,1,61,0,156,0,6,1,0,1,94,1,63,0,0,0,0,0,0,0,69,255,236,255,236,255,237,255,106,0,0,0,0,0,0,0,0,0,0,0,0,0,149,0,69,0,31,0,69,0,69,0,88,0,88,0,88,255,204,255,182,0,67,0,54,0,76,0,25,0,222,2,4,0,193,0,193,0,0,0,0,0,0,0,0,0,76,0,0,0,76,0,0,0,76, +0,0,0,76,0,0,0,152,0,0,0,220,0,0,1,152,0,0,2,152,0,0,3,160,0,0,4,252,0,0,5,44,0,0,5,132,0,0,5,220,0,0,6,120,0,0,6,208,0,0,7,12,0,0,7,56,0,0,7,100,0,0,7,152,0,0,9,32,0,0,9,120,0,0,10,40,0,0,10,232,0,0,11,100,0,0,12,0,0,0,12,184,0,0,13,20,0,0,13,232,0, +0,14,156,0,0,14,224,0,0,15,52,0,0,15,128,0,0,15,196,0,0,16,12,0,0,16,244,0,0,18,8,0,0,18,216,0,0,19,128,0,0,20,12,0,0,20,128,0,0,20,220,0,0,21,44,0,0,21,208,0,0,22,40,0,0,22,128,0,0,22,236,0,0,23,188,0,0,23,244,0,0,24,180,0,0,25,80,0,0,25,208,0,0,26, +68,0,0,26,236,0,0,27,184,0,0,28,180,0,0,28,248,0,0,29,132,0,0,29,248,0,0,31,16,0,0,32,20,0,0,32,156,0,0,33,16,0,0,33,84,0,0,33,140,0,0,33,208,0,0,34,20,0,0,34,64,0,0,34,132,0,0,35,112,0,0,36,0,0,0,36,136,0,0,37,24,0,0,37,192,0,0,38,56,0,0,39,0,0,0,39, +112,0,0,39,216,0,0,40,80,0,0,41,76,0,0,41,164,0,0,42,176,0,0,43,32,0,0,43,152,0,0,44,44,0,0,44,192,0,0,45,80,0,0,46,60,0,0,46,176,0,0,47,32,0,0,47,172,0,0,48,248,0,0,49,228,0,0,50,208,0,0,51,88,0,0,52,36,0,0,52,84,0,0,53,36,0,0,53,164,0,0,53,164,0,0, +53,244,0,0,54,184,0,0,55,76,0,0,56,100,0,0,57,56,0,0,57,132,0,0,58,168,0,0,58,236,0,0,60,8,0,0,60,236,0,0,61,96,0,0,61,152,0,0,61,196,0,0,63,44,0,0,63,88,0,0,63,208,0,0,64,60,0,0,64,240,0,0,65,192,0,0,66,4,0,0,66,180,0,0,67,16,0,0,67,64,0,0,67,80,0,0, +67,184,0,0,68,72,0,0,68,192,0,0,68,224,0,0,69,0,0,0,69,32,0,0,70,20,0,0,70,56,0,0,70,92,0,0,70,140,0,0,70,184,0,0,70,240,0,0,72,36,0,0,72,220,0,0,72,244,0,0,73,12,0,0,73,36,0,0,73,60,0,0,73,84,0,0,73,108,0,0,73,132,0,0,73,172,0,0,73,208,0,0,74,108,0, +0,74,152,0,0,74,188,0,0,74,224,0,0,75,16,0,0,75,60,0,0,75,116,0,0,75,232,0,0,76,236,0,0,77,16,0,0,77,52,0,0,77,100,0,0,77,156,0,0,77,192,0,0,78,64,0,0,79,36,0,0,79,60,0,0,79,84,0,0,79,108,0,0,79,132,0,0,79,156,0,0,79,180,0,0,81,4,0,0,81,28,0,0,81,52, +0,0,81,76,0,0,81,100,0,0,81,132,0,0,81,156,0,0,81,180,0,0,81,216,0,0,81,248,0,0,83,12,0,0,83,36,0,0,83,60,0,0,83,84,0,0,83,124,0,0,83,172,0,0,83,220,0,0,84,56,0,0,85,60,0,0,85,84,0,0,85,108,0,0,85,148,0,0,85,196,0,0,85,220,0,0,86,112,0,0,86,136,0,0,86, +180,0,0,86,204,0,0,86,252,0,0,87,20,0,0,87,44,0,0,87,68,0,0,87,92,0,0,87,116,0,0,87,140,0,0,87,164,0,0,87,188,0,0,87,212,0,0,87,236,0,0,88,4,0,0,88,28,0,0,88,68,0,0,88,84,0,0,89,16,0,0,89,40,0,0,89,64,0,0,89,88,0,0,89,112,0,0,89,136,0,0,89,160,0,0,89, +184,0,0,89,208,0,0,89,232,0,0,90,0,0,0,90,24,0,0,90,48,0,0,90,72,0,0,90,96,0,0,90,120,0,0,90,144,0,0,90,168,0,0,90,192,0,0,90,240,0,0,91,36,0,0,91,176,0,0,92,68,0,0,92,120,0,0,92,144,0,0,92,184,0,0,92,208,0,0,92,248,0,0,93,16,0,0,93,40,0,0,93,64,0,0, +93,88,0,0,93,168,0,0,94,80,0,0,95,0,0,0,95,24,0,0,95,48,0,0,95,72,0,0,95,96,0,0,96,92,0,0,96,128,0,0,96,180,0,0,96,204,0,0,96,228,0,0,96,252,0,0,97,20,0,0,97,44,0,0,97,68,0,0,97,184,0,0,98,72,0,0,98,96,0,0,98,120,0,0,98,144,0,0,98,168,0,0,98,192,0,0, +98,216,0,0,98,240,0,0,99,128,0,0,100,24,0,0,100,68,0,0,100,100,0,0,100,140,0,0,100,180,0,0,100,204,0,0,100,228,0,0,101,124,0,0,102,148,0,0,102,172,0,0,102,196,0,0,102,220,0,0,102,244,0,0,103,12,0,0,103,36,0,0,103,60,0,0,103,84,0,0,103,108,0,0,103,132, +0,0,103,156,0,0,103,180,0,0,103,204,0,0,103,228,0,0,103,252,0,0,104,20,0,0,104,56,0,0,104,80,0,0,104,184,0,0,105,76,0,0,105,120,0,0,105,160,0,0,105,204,0,0,105,236,0,0,106,20,0,0,106,60,0,0,106,84,0,0,106,108,0,0,106,132,0,0,106,156,0,0,106,180,0,0,106, +204,0,0,106,240,0,0,107,16,0,0,107,52,0,0,107,76,0,0,107,112,0,0,107,136,0,0,107,160,0,0,107,184,0,0,107,208,0,0,107,232,0,0,108,0,0,0,108,100,0,0,108,216,0,0,109,152,0,0,109,168,0,0,110,12,0,0,110,100,0,0,110,212,0,0,111,96,0,0,111,212,0,0,112,64,0, +0,112,80,0,0,112,180,0,0,113,8,0,0,113,108,0,0,114,24,0,0,114,116,0,0,115,20,0,0,115,200,0,0,116,12,0,0,116,120,0,0,116,252,0,0,117,88,0,0,117,208,0,0,118,16,0,0,118,92,0,0,118,184,0,0,119,12,0,0,119,84,0,0,119,160,0,0,120,8,0,0,120,76,0,0,120,144,0, +0,120,252,0,0,121,20,0,0,121,44,0,0,121,144,0,0,121,252,0,0,122,108,0,0,122,240,0,0,123,92,0,0,123,212,0,0,124,76,0,0,124,92,0,0,124,200,0,0,125,44,0,0,125,104,0,0,125,196,0,0,126,4,0,0,126,32,0,0,126,60,0,0,126,168,0,0,126,252,0,0,127,84,0,0,127,184, +0,0,128,0,0,0,128,72,0,0,128,180,0,0,129,32,0,0,129,140,0,0,129,248,0,0,130,100,0,0,130,208,0,0,131,48,0,0,131,148,0,0,131,232,0,0,132,4,0,0,132,32,0,0,132,100,0,0,132,116,0,0,132,140,0,0,132,164,0,0,132,188,0,0,132,212,0,0,132,236,0,0,133,4,0,0,133, +52,0,0,133,76,0,0,133,108,0,0,133,140,0,0,133,172,0,0,133,204,0,0,133,236,0,0,134,12,0,0,134,44,0,0,134,68,0,0,134,84,0,0,134,116,0,0,134,140,0,0,134,172,0,0,134,196,0,0,134,220,0,0,134,244,0,0,135,12,0,0,135,36,0,0,135,60,0,0,135,84,0,0,135,108,0,0, +135,132,0,0,135,156,0,0,135,180,0,0,135,204,0,0,135,228,0,0,135,252,0,0,136,20,0,0,136,44,0,0,136,144,0,0,136,168,0,0,136,192,0,0,136,216,0,0,136,240,0,0,137,8,0,0,137,32,0,0,137,56,0,0,137,80,0,0,137,104,0,0,137,128,0,0,137,152,0,0,137,176,0,0,137,200, +0,0,137,224,0,0,137,248,0,0,138,16,0,0,138,40,0,0,138,64,0,0,138,88,0,0,138,112,0,0,138,136,0,0,138,160,0,0,138,184,0,0,138,208,0,0,138,232,0,0,139,0,0,0,139,24,0,0,139,48,0,0,139,72,0,0,139,96,0,0,139,120,0,0,139,144,0,0,139,168,0,0,139,192,0,0,140, +76,0,0,140,224,0,0,140,248,0,0,141,16,0,0,141,84,0,0,141,244,0,0,142,68,0,0,142,148,0,0,142,172,0,0,142,196,0,0,142,220,0,0,142,244,0,0,143,20,0,0,143,44,0,0,143,76,0,0,143,100,0,0,143,124,0,0,143,148,0,0,143,180,0,0,143,204,0,0,143,228,0,0,143,252,0, +0,144,96,0,0,144,236,0,0,145,96,0,0,145,192,0,0,146,92,0,0,146,248,0,0,147,88,0,0,147,236,0,0,148,120,0,0,148,176,0,0,148,252,0,0,149,156,0,0,149,240,0,0,150,68,0,0,150,192,0,0,151,64,0,0,151,104,0,0,151,212,0,0,152,40,0,0,152,164,0,0,153,52,0,0,153, +196,0,0,154,112,0,0,154,248,0,0,155,120,0,0,155,236,0,0,156,100,0,0,156,200,0,0,157,104,0,0,157,240,0,0,158,184,0,0,159,108,0,0,160,40,0,0,160,168,0,0,160,240,0,0,161,128,0,0,161,244,0,0,162,96,0,0,162,204,0,0,163,28,0,0,163,96,0,0,163,188,0,0,164,48, +0,0,164,128,0,0,164,180,0,0,164,228,0,0,165,88,0,0,165,184,0,0,165,236,0,0,166,116,0,0,166,220,0,0,167,68,0,0,167,196,0,0,168,36,0,0,168,136,0,0,168,184,0,0,169,36,0,0,169,136,0,0,170,24,0,0,170,176,0,0,170,236,0,0,171,40,0,0,171,120,0,0,171,184,0,0, +172,12,0,0,172,76,0,0,172,136,0,0,172,248,0,0,173,104,0,0,174,12,0,0,174,76,0,0,174,172,0,0,174,244,0,0,175,88,0,0,175,156,0,0,175,224,0,0,176,72,0,0,176,184,0,0,177,36,0,0,177,76,0,0,177,132,0,0,177,196,0,0,177,244,0,0,178,60,0,0,178,152,0,0,179,0,0, +0,179,144,0,0,179,236,0,0,180,76,0,0,180,172,0,0,181,32,0,0,181,164,0,0,182,60,0,0,182,196,0,0,183,84,0,0,183,132,0,0,183,232,0,0,184,32,0,0,184,64,0,0,184,196,0,0,185,52,0,0,185,164,0,0,186,32,0,0,186,236,0,0,187,144,0,0,188,64,0,0,188,204,0,0,189,136, +0,0,190,20,0,0,190,192,0,0,190,252,0,0,191,96,0,0,191,160,0,0,191,240,0,0,192,88,0,0,192,188,0,0,193,28,0,0,193,84,0,0,193,148,0,0,193,212,0,0,194,52,0,0,194,160,0,0,194,216,0,0,195,24,0,0,195,40,0,0,195,56,0,0,195,72,0,0,195,88,0,0,195,148,0,0,195,208, +0,0,196,44,0,0,196,136,0,0,196,228,0,0,197,64,0,0,197,112,0,0,197,128,0,0,197,176,0,0,197,192,0,0,197,212,0,0,197,232,0,0,198,16,0,0,198,44,0,0,198,64,0,0,198,84,0,0,198,128,0,0,198,156,0,0,198,172,0,0,198,188,0,0,199,96,0,0,199,196,0,0,200,220,0,0,200, +236,0,0,201,40,0,0,201,124,0,0,201,176,0,0,202,44,0,0,202,100,0,0,202,192,0,0,202,224,0,0,203,4,0,0,203,44,0,0,203,84,0,0,203,116,0,0,203,132,0,0,203,148,0,0,203,164,0,0,203,180,0,0,203,196,0,0,203,212,0,0,204,0,0,0,204,16,0,0,204,100,0,0,204,148,0,0, +204,164,0,0,204,236,0,0,204,252,0,0,205,76,0,0,205,92,0,0,205,120,0,0,205,148,0,0,205,192,0,0,205,216,0,0,206,16,0,0,206,44,0,0,206,84,0,0,206,120,0,0,206,148,0,0,206,168,0,0,206,188,0,0,206,224,0,0,207,4,0,0,207,36,0,0,207,104,0,0,207,152,0,0,207,188, +0,0,207,224,0,0,208,12,0,0,208,40,0,0,208,88,0,0,208,136,0,0,208,180,0,0,208,244,0,0,209,96,0,0,209,140,0,0,210,8,0,0,210,24,0,0,210,52,0,0,210,88,0,0,210,160,0,0,210,224,0,0,211,28,0,0,211,112,0,0,211,164,0,0,212,132,0,0,212,176,0,0,212,192,0,0,212, +208,0,0,212,224,0,0,212,252,0,0,213,20,0,0,213,48,0,0,213,76,0,0,213,124,0,0,213,160,0,0,213,204,0,0,214,20,0,0,214,72,0,0,214,168,0,0,214,192,0,0,214,208,0,0,214,228,0,0,215,36,0,0,215,68,0,0,215,96,0,0,215,112,0,0,215,128,0,0,215,168,0,0,215,184,0, +0,215,208,0,0,215,232,0,0,215,248,0,0,216,8,0,0,216,24,0,0,216,48,0,0,216,72,0,0,216,88,0,0,216,112,0,0,216,136,0,0,216,160,0,0,216,184,0,0,216,208,0,0,216,232,0,0,217,0,0,0,217,16,0,0,217,32,0,0,217,48,0,0,217,144,0,0,217,160,0,0,217,176,0,0,217,192, +0,0,218,96,0,0,218,112,0,0,218,128,0,0,218,216,0,0,218,232,0,0,218,248,0,0,219,88,0,0,219,104,0,0,219,120,0,0,219,136,0,0,219,252,0,0,220,12,0,0,220,28,0,0,220,252,0,0,221,12,0,0,221,176,0,0,222,88,0,0,222,112,0,0,222,136,0,0,222,160,0,0,222,184,0,0, +222,208,0,0,222,232,0,0,223,0,0,0,223,144,0,0,224,4,0,0,224,64,0,0,224,228,0,0,224,244,0,0,225,92,0,0,225,204,0,0,226,116,0,0,226,204,0,0,226,220,0,0,227,28,0,0,227,44,0,0,227,124,0,0,227,248,0,0,228,8,0,0,228,84,0,0,228,228,0,0,229,88,0,0,229,236,0, +0,230,76,0,0,230,176,0,0,231,132,0,0,231,224,0,0,232,60,0,0,232,192,0,0,232,216,0,0,232,240,0,0,233,8,0,0,233,32,0,0,233,56,0,0,233,196,0,0,234,72,0,0,234,176,0,0,234,200,0,0,234,224,0,0,235,104,0,0,235,220,0,0,236,124,0,0,236,228,0,0,237,72,0,0,237, +184,0,0,238,44,0,0,238,60,0,0,238,168,0,0,239,4,0,0,239,48,0,0,239,164,0,0,240,0,0,0,240,156,0,0,241,12,0,0,241,28,0,0,241,44,0,0,241,152,0,0,242,8,0,0,242,120,0,0,242,136,0,0,242,152,0,0,242,168,0,0,242,228,0,0,243,28,0,0,243,140,0,0,243,232,0,0,244, +0,0,0,244,24,0,0,244,48,0,0,244,72,0,0,244,216,0,0,244,240,0,0,245,152,0,0,245,168,0,0,245,184,0,0,245,220,0,0,245,236,0,0,246,80,0,0,246,172,0,0,247,28,0,0,247,52,0,0,247,76,0,0,247,100,0,0,247,148,0,0,247,164,0,0,248,44,0,0,248,60,0,0,248,116,0,0,249, +4,0,0,249,20,0,0,249,224,0,0,249,240,0,0,250,92,0,0,250,116,0,0,250,132,0,0,250,232,0,0,250,248,0,0,251,8,0,0,251,24,0,0,251,92,0,0,251,108,0,0,251,124,0,0,251,140,0,0,252,28,0,0,252,248,0,0,253,8,0,0,253,92,0,0,253,192,0,0,254,20,0,0,254,124,0,0,254, +240,0,0,255,112,0,0,255,228,0,1,0,140,0,1,1,68,0,1,1,224,0,1,1,240,0,1,2,188,0,1,3,84,0,1,3,140,0,1,4,20,0,1,4,36,0,1,4,240,0,1,5,0,0,1,5,108,0,1,5,132,0,1,5,148,0,1,5,248,0,1,6,128,0,1,6,212,0,1,6,228,0,1,7,40,0,1,7,56,0,1,7,72,0,1,7,140,0,1,7,156,0, +1,8,116,0,1,8,132,0,1,8,216,0,1,9,60,0,1,9,144,0,1,9,244,0,1,10,104,0,1,10,228,0,1,11,84,0,1,12,8,0,1,12,176,0,1,13,68,0,1,13,92,0,1,13,116,0,1,13,216,0,1,13,240,0,1,14,168,0,1,14,184,0,1,14,200,0,1,14,232,0,1,14,248,0,1,15,92,0,1,15,172,0,1,16,4,0,1, +16,28,0,1,16,52,0,1,16,76,0,1,16,124,0,1,16,212,0,1,17,44,0,1,17,60,0,1,17,76,0,1,17,144,0,1,17,212,0,1,18,8,0,1,18,60,0,1,18,152,0,1,18,248,0,1,19,84,0,1,19,176,0,1,19,200,0,1,19,224,0,1,20,32,0,1,20,96,0,1,20,156,0,1,20,216,0,1,21,12,0,1,21,64,0,1, +21,88,0,1,21,112,0,1,21,160,0,1,21,208,0,1,21,224,0,1,22,16,0,1,22,84,0,1,22,144,0,1,22,216,0,1,23,32,0,1,23,128,0,1,23,144,0,1,23,160,0,1,23,184,0,1,23,208,0,1,24,48,0,1,24,148,0,1,24,220,0,1,25,36,0,1,25,140,0,1,25,224,0,1,25,252,0,1,26,44,0,1,26,68, +0,1,26,124,0,1,26,148,0,1,26,164,0,1,26,180,0,1,26,204,0,1,26,228,0,1,26,244,0,1,27,4,0,1,27,28,0,1,27,52,0,1,27,76,0,1,27,100,0,1,27,124,0,1,27,148,0,1,27,164,0,1,27,180,0,1,27,204,0,1,27,228,0,1,27,252,0,1,28,20,0,1,28,76,0,1,28,120,0,1,28,136,0,1, +28,152,0,1,28,176,0,1,28,200,0,1,28,224,0,1,28,248,0,1,29,16,0,1,29,40,0,1,29,64,0,1,29,88,0,1,29,112,0,1,29,136,0,1,29,160,0,1,29,184,0,1,29,228,0,1,30,16,0,1,30,40,0,1,30,64,0,1,30,80,0,1,30,96,0,1,30,112,0,1,30,128,0,1,30,144,0,1,30,160,0,1,31,28, +0,1,31,116,0,1,31,232,0,1,32,64,0,1,32,152,0,1,33,16,0,1,33,60,0,1,33,144,0,1,34,52,0,1,34,168,0,1,34,248,0,1,35,24,0,1,35,116,0,1,36,40,0,1,36,120,0,1,36,212,0,1,37,128,0,1,37,212,0,1,38,76,0,1,38,160,0,1,39,64,0,1,39,148,0,1,40,28,0,1,40,104,0,1,40, +220,0,1,41,52,0,1,41,244,0,1,42,76,0,1,42,156,0,1,42,244,0,1,43,148,0,1,43,228,0,1,44,164,0,1,44,204,0,1,45,84,0,1,45,220,0,1,45,236,0,1,46,160,0,1,46,176,0,1,46,212,0,1,46,228,0,1,47,44,0,1,47,60,0,1,47,184,0,1,47,216,0,1,48,76,0,1,48,152,0,1,49,0,0, +1,49,76,0,1,49,152,0,1,49,252,0,1,50,40,0,1,50,112,0,1,51,20,0,1,51,136,0,1,51,200,0,1,51,232,0,1,52,104,0,1,52,248,0,1,53,60,0,1,53,76,0,1,54,16,0,1,54,88,0,1,55,8,0,1,55,80,0,1,55,124,0,1,55,196,0,1,56,76,0,1,56,92,0,1,56,232,0,1,57,96,0,1,58,32,0, +1,58,140,0,1,58,156,0,1,58,228,0,1,59,100,0,1,59,168,0,1,59,184,0,1,59,216,0,1,60,92,0,1,60,208,0,1,60,224,0,1,61,132,0,1,61,204,0,1,61,240,0,1,62,28,0,1,62,184,0,1,63,100,0,1,63,164,0,1,63,240,0,1,64,16,0,1,64,108,0,1,64,156,0,1,65,12,0,1,65,124,0,1, +65,148,0,1,65,172,0,1,65,196,0,1,65,220,0,1,65,244,0,1,66,16,0,1,66,40,0,1,66,64,0,1,66,88,0,1,66,112,0,1,66,136,0,1,66,244,0,1,67,12,0,1,67,96,0,1,67,120,0,1,67,188,0,1,67,212,0,1,68,148,0,1,68,172,0,1,69,96,0,1,69,120,0,1,69,220,0,1,69,244,0,1,70,116, +0,1,70,140,0,1,70,164,0,1,70,188,0,1,70,212,0,1,71,144,0,1,71,236,0,1,72,120,0,1,72,144,0,1,72,248,0,1,73,120,0,1,74,28,0,1,74,52,0,1,74,96,0,1,75,0,0,1,75,44,0,1,75,72,0,1,75,216,0,1,75,244,0,1,76,120,0,1,76,188,0,1,77,0,0,1,77,16,0,1,77,36,0,1,77,76, +0,1,77,104,0,1,77,152,0,1,77,240,0,1,78,108,0,1,78,240,0,1,79,92,0,1,79,164,0,1,79,244,0,1,80,68,0,1,80,196,0,1,80,248,0,1,81,56,0,1,81,92,0,1,81,144,0,1,81,232,0,1,82,0,0,1,82,24,0,1,82,48,0,1,82,72,0,1,82,96,0,1,82,120,0,1,82,144,0,1,82,168,0,1,82, +192,0,1,82,216,0,1,82,240,0,1,83,8,0,1,83,32,0,1,83,168,0,1,83,192,0,1,84,144,0,1,84,160,0,1,84,176,0,1,84,192,0,1,84,208,0,1,84,224,0,1,85,96,0,1,85,228,0,1,86,76,0,1,86,92,0,1,86,108,0,1,86,124,0,1,87,28,0,1,87,220,0,1,88,108,0,1,89,36,0,1,89,148,0, +1,90,20,0,1,90,200,0,1,91,92,0,1,91,232,0,1,92,104,0,1,92,216,0,1,93,152,0,1,94,0,0,1,94,100,0,1,94,196,0,1,95,156,0,1,96,40,0,1,96,184,0,1,97,72,0,1,97,148,0,1,98,40,0,1,98,192,0,1,99,92,0,1,99,204,0,1,100,140,0,1,101,56,0,1,101,212,0,1,102,140,0,1, +103,12,0,1,103,40,0,1,103,136,0,1,103,212,0,1,103,236,0,1,104,48,0,1,104,124,0,1,104,204,0,1,105,36,0,1,105,108,0,1,105,188,0,1,106,32,0,1,106,116,0,1,106,144,0,1,106,240,0,1,107,140,0,1,107,184,0,1,107,204,0,1,107,252,0,1,108,80,0,1,108,180,0,1,109, +48,0,1,109,188,0,1,110,24,0,1,110,148,0,1,111,16,0,1,111,136,0,1,111,212,0,1,112,60,0,1,112,160,0,1,113,4,0,1,113,104,0,1,113,212,0,1,114,68,0,1,114,160,0,1,115,32,0,1,115,112,0,1,115,204,0,1,116,80,0,1,116,240,0,1,117,88,0,1,117,224,0,1,118,60,0,1,118, +188,0,1,119,44,0,1,119,164,0,1,119,244,0,1,120,116,0,1,121,8,0,1,121,88,0,1,121,196,0,1,122,68,0,1,122,252,0,1,123,100,0,1,123,208,0,1,124,72,0,1,124,204,0,1,125,84,0,1,125,200,0,1,126,44,0,1,126,156,0,1,127,0,0,1,127,52,0,1,127,132,0,1,128,68,0,1,128, +208,0,1,129,8,0,1,129,176,0,1,129,228,0,1,130,24,0,1,130,92,0,1,130,184,0,1,131,32,0,1,131,84,0,1,131,156,0,1,132,4,0,1,132,68,0,1,132,116,0,1,132,164,0,1,133,0,0,1,133,48,0,1,133,96,0,1,133,160,0,1,133,216,0,1,133,248,0,1,134,48,0,1,134,96,0,1,134,144, +0,1,134,216,0,1,135,28,0,1,135,124,0,1,135,164,0,1,136,8,0,1,136,64,0,1,136,188,0,1,137,56,0,1,137,140,0,1,138,72,0,1,138,156,0,1,138,244,0,1,139,80,0,1,139,172,0,1,140,32,0,1,140,148,0,1,141,8,0,1,141,64,0,1,141,120,0,1,141,224,0,1,142,64,0,1,142,140, +0,1,142,220,0,1,143,12,0,1,143,60,0,1,143,144,0,1,143,208,0,1,144,20,0,1,144,88,0,1,144,192,0,1,144,232,0,1,144,252,0,1,145,16,0,1,145,36,0,1,145,56,0,1,145,180,0,1,145,196,0,1,146,12,0,1,146,96,0,1,146,180,0,1,147,4,0,1,147,136,0,1,148,8,0,1,148,124, +0,1,148,188,0,1,149,4,0,1,149,112,0,1,149,180,0,1,149,248,0,1,150,44,0,1,150,92,0,1,150,152,0,1,150,244,0,1,151,40,0,1,151,120,0,1,151,152,0,1,152,32,0,1,152,136,0,1,152,220,0,1,153,72,0,1,153,120,0,1,153,232,0,1,154,124,0,1,155,40,0,1,155,112,0,1,155, +212,0,1,156,60,0,1,156,152,0,1,156,236,0,1,157,20,0,1,157,68,0,1,157,144,0,1,157,236,0,1,158,72,0,1,158,160,0,1,158,184,0,1,158,208,0,1,158,232,0,1,159,0,0,1,159,24,0,1,159,48,0,1,159,72,0,1,159,96,0,1,159,128,0,1,159,156,0,1,159,180,0,1,159,204,0,1, +159,228,0,1,159,252,0,1,160,20,0,1,160,44,0,1,160,68,0,1,160,92,0,1,160,116,0,1,160,140,0,1,160,164,0,1,160,188,0,1,160,212,0,1,160,236,0,1,161,8,0,1,161,36,0,1,161,60,0,1,161,84,0,1,161,108,0,1,161,132,0,1,161,156,0,1,161,180,0,1,161,204,0,1,161,228, +0,1,161,252,0,1,162,20,0,1,162,44,0,1,162,68,0,1,162,92,0,1,162,116,0,1,162,140,0,1,162,164,0,1,162,188,0,1,162,212,0,1,162,236,0,1,163,4,0,1,163,28,0,1,163,52,0,1,163,76,0,1,163,100,0,1,163,124,0,1,163,148,0,1,163,172,0,1,163,196,0,1,163,220,0,1,163, +244,0,1,164,12,0,1,164,36,0,1,164,60,0,1,164,84,0,1,164,108,0,1,164,132,0,1,164,156,0,1,164,180,0,1,164,204,0,1,164,228,0,1,164,252,0,1,165,20,0,1,165,44,0,1,165,68,0,1,165,100,0,1,165,132,0,1,165,156,0,1,165,180,0,1,165,204,0,1,165,228,0,1,165,252,0, +1,166,20,0,1,166,44,0,1,166,68,0,1,166,92,0,1,166,116,0,1,166,140,0,1,166,164,0,1,166,188,0,1,166,212,0,1,166,236,0,1,167,4,0,1,167,32,0,1,167,60,0,1,167,84,0,1,167,108,0,1,167,132,0,1,167,156,0,1,167,180,0,1,167,204,0,1,167,228,0,1,167,252,0,1,168,20, +0,1,168,44,0,1,168,68,0,1,168,92,0,1,168,116,0,1,168,140,0,1,168,172,0,1,168,204,0,1,168,228,0,1,168,252,0,1,169,20,0,1,169,44,0,1,169,68,0,1,169,92,0,1,169,116,0,1,169,140,0,1,169,164,0,1,169,188,0,1,169,212,0,1,169,236,0,1,170,4,0,1,170,28,0,1,170, +52,0,1,170,76,0,1,170,100,0,1,170,124,0,1,170,148,0,1,170,172,0,1,170,196,0,1,170,220,0,1,170,244,0,1,171,12,0,1,171,36,0,1,171,60,0,1,171,84,0,1,171,108,0,1,171,132,0,1,171,156,0,1,171,180,0,1,171,196,0,1,171,220,0,1,171,244,0,1,172,12,0,1,172,36,0, +1,172,68,0,1,172,92,0,1,172,116,0,1,172,140,0,1,172,164,0,1,172,188,0,1,172,212,0,1,172,236,0,1,173,4,0,1,173,28,0,1,173,52,0,1,173,76,0,1,173,100,0,1,173,124,0,1,173,148,0,1,173,172,0,1,173,196,0,1,173,220,0,1,173,244,0,1,174,12,0,1,174,36,0,1,174,60, +0,1,174,84,0,1,174,108,0,1,174,132,0,1,174,156,0,1,174,180,0,1,174,204,0,1,174,228,0,1,174,252,0,1,175,20,0,1,175,44,0,1,175,68,0,1,175,92,0,1,175,116,0,1,175,140,0,1,175,164,0,1,175,188,0,1,175,212,0,1,175,236,0,1,176,4,0,1,176,28,0,1,176,52,0,1,176, +76,0,1,176,100,0,1,176,124,0,1,176,148,0,1,176,172,0,1,176,196,0,1,176,220,0,1,176,244,0,1,177,12,0,1,177,36,0,1,177,60,0,1,177,84,0,1,177,108,0,1,177,132,0,1,177,156,0,1,177,180,0,1,177,204,0,1,177,228,0,1,177,252,0,1,178,20,0,1,178,44,0,1,178,68,0, +1,178,92,0,1,178,116,0,1,178,140,0,1,178,164,0,1,178,188,0,1,178,212,0,1,178,236,0,1,179,4,0,1,179,28,0,1,179,52,0,1,179,76,0,1,179,100,0,1,179,124,0,1,179,148,0,1,179,172,0,1,179,196,0,1,179,220,0,1,179,244,0,1,180,12,0,1,180,36,0,1,180,60,0,1,180,84, +0,1,180,108,0,1,180,132,0,1,180,156,0,1,180,180,0,1,180,204,0,1,180,228,0,1,180,252,0,1,181,20,0,1,181,44,0,1,181,68,0,1,181,92,0,1,181,116,0,1,181,140,0,1,181,164,0,1,181,188,0,1,181,212,0,1,181,236,0,1,182,4,0,1,182,28,0,1,182,52,0,1,182,76,0,1,182, +100,0,1,182,124,0,1,182,148,0,1,182,172,0,1,182,196,0,1,182,220,0,1,182,244,0,1,183,12,0,1,183,36,0,1,183,60,0,1,183,84,0,1,183,108,0,1,183,132,0,1,183,156,0,1,183,180,0,1,183,204,0,1,183,228,0,1,183,252,0,1,184,20,0,1,184,44,0,1,184,68,0,1,184,92,0, +1,184,116,0,1,184,140,0,1,184,164,0,1,184,188,0,1,184,212,0,1,184,236,0,1,185,4,0,1,185,28,0,1,185,52,0,1,185,76,0,1,185,100,0,1,185,116,0,1,185,140,0,1,185,156,0,1,185,180,0,1,185,196,0,1,185,220,0,1,185,236,0,1,186,4,0,1,186,20,0,1,186,44,0,1,186,60, +0,1,186,84,0,1,186,100,0,1,186,124,0,1,186,148,0,1,186,172,0,1,186,196,0,1,186,220,0,1,186,244,0,1,187,12,0,1,187,36,0,1,187,60,0,1,187,84,0,1,187,108,0,1,187,132,0,1,187,156,0,1,187,180,0,1,187,204,0,1,187,228,0,1,187,252,0,1,188,20,0,1,188,44,0,1,188, +68,0,1,188,92,0,1,188,116,0,1,188,140,0,1,188,164,0,1,188,188,0,1,188,212,0,1,188,236,0,1,189,4,0,1,189,28,0,1,189,52,0,1,189,76,0,1,189,100,0,1,189,124,0,1,189,148,0,1,189,172,0,1,189,196,0,1,189,220,0,1,189,244,0,1,190,12,0,1,190,36,0,1,190,60,0,1, +190,84,0,1,190,108,0,1,190,132,0,1,190,156,0,1,190,180,0,1,190,204,0,1,190,228,0,1,190,252,0,1,191,20,0,1,191,44,0,1,191,68,0,1,191,92,0,1,191,116,0,1,191,140,0,1,191,164,0,1,191,188,0,1,191,212,0,1,191,228,0,1,191,252,0,1,192,12,0,1,192,28,0,1,192,64, +0,1,192,80,0,1,192,104,0,1,192,128,0,1,192,152,0,1,192,176,0,1,192,200,0,1,192,224,0,1,192,248,0,1,193,8,0,1,193,32,0,1,193,48,0,1,193,72,0,1,193,100,0,1,193,124,0,1,193,148,0,1,193,172,0,1,193,196,0,1,193,220,0,1,193,236,0,1,194,4,0,1,194,28,0,1,194, +52,0,1,194,76,0,1,194,100,0,1,194,116,0,1,194,144,0,1,194,168,0,1,194,192,0,1,194,216,0,1,194,240,0,1,195,8,0,1,195,24,0,1,195,48,0,1,195,72,0,1,195,96,0,1,195,120,0,1,195,144,0,1,195,168,0,1,195,192,0,1,195,208,0,1,195,232,0,1,196,0,0,1,196,16,0,1,196, +32,0,1,196,56,0,1,196,80,0,1,196,104,0,1,196,128,0,1,196,152,0,1,196,176,0,1,196,192,0,1,196,216,0,1,196,232,0,1,197,0,0,1,197,16,0,1,197,52,0,1,197,52,0,1,197,52,0,1,197,52,0,1,197,52,0,1,197,52,0,1,197,52,0,1,197,52,0,1,197,52,0,1,197,52,0,1,197,52, +0,1,197,52,0,1,197,96,0,1,197,112,0,1,197,156,0,1,197,200,0,1,197,240,0,1,198,24,0,1,198,52,0,1,198,76,0,1,198,136,0,1,198,196,0,1,199,0,0,1,199,36,0,1,199,128,0,1,199,220,0,1,200,60,0,1,200,112,0,1,200,200,0,1,201,76,0,1,201,140,0,1,201,168,0,1,202, +0,0,1,202,0,0,1,203,80,0,1,204,124,0,1,204,156,0,1,204,184,0,1,204,216,0,1,204,244,0,1,205,16,0,1,205,48,0,1,205,116,0,1,205,188,0,1,205,216,0,1,206,84,0,1,206,104,0,1,206,160,0,1,206,208,0,1,207,0,0,1,207,28,0,1,207,56,0,1,207,84,0,1,207,140,0,1,207, +140,0,1,208,20,0,1,208,76,0,1,208,188,0,1,209,36,0,1,209,164,0,1,209,204,0,1,210,132,0,1,211,16,0,1,211,64,0,1,211,92,0,1,211,132,0,1,211,184,0,1,211,236,0,1,212,80,0,1,212,100,0,1,212,120,0,1,212,140,0,1,212,160,0,1,212,180,0,1,212,200,0,1,212,220,0, +1,212,240,0,1,213,4,0,1,213,24,0,1,213,44,0,1,213,64,0,1,213,84,0,1,213,104,0,1,213,124,0,1,213,144,0,1,213,164,0,1,213,184,0,1,213,204,0,1,213,224,0,1,213,244,0,1,214,8,0,1,214,28,0,1,214,48,0,1,214,68,0,1,214,88,0,1,214,108,0,1,214,128,0,1,214,244, +0,1,215,164,0,1,216,52,0,1,216,116,0,1,216,220,0,1,217,92,0,1,217,224,0,1,218,192,0,1,219,140,0,1,220,48,0,1,220,144,0,1,220,168,0,1,221,184,0,1,222,0,0,1,222,88,0,1,223,228,0,1,224,128,0,1,225,0,0,1,225,148,0,1,226,0,0,1,226,160,0,1,227,52,0,1,227,104, +0,1,227,228,0,1,228,72,0,1,228,168,0,1,229,28,0,1,229,184,0,1,230,8,0,1,230,100,0,1,230,204,0,1,231,16,0,1,231,140,0,1,232,68,0,1,232,180,0,1,233,76,0,1,233,252,0,1,234,176,0,1,234,240,0,1,235,0,0,1,235,16,0,1,235,32,0,1,235,168,0,1,235,244,0,1,236,20, +0,1,236,52,0,1,236,84,0,1,236,116,0,1,236,148,0,1,236,180,0,1,236,212,0,1,236,244,0,1,237,20,0,1,237,52,0,1,237,84,0,1,237,116,0,1,237,148,0,1,237,180,0,1,237,204,0,1,237,236,0,1,238,28,0,1,238,80,0,1,238,132,0,1,238,180,0,1,238,252,0,1,239,68,0,1,239, +116,0,1,239,164,0,1,239,208,0,1,239,252,0,1,240,68,0,1,240,140,0,1,241,52,0,1,241,220,0,1,242,36,0,1,242,108,0,1,242,180,0,1,242,252,0,1,243,60,0,1,243,124,0,1,243,184,0,1,243,244,0,1,244,48,0,1,244,108,0,1,244,184,0,1,245,64,0,1,245,204,0,1,246,144, +0,1,247,84,0,1,248,108,0,1,248,204,0,1,249,16,0,1,249,72,0,1,249,128,0,1,249,184,0,1,249,240,0,1,250,40,0,1,250,96,0,1,250,236,0,1,251,124,0,1,251,184,0,1,252,32,0,1,252,200,0,1,253,112,0,1,253,148,0,1,253,188,0,1,253,228,0,1,254,12,0,1,254,52,0,1,254, +92,0,1,254,128,0,1,254,164,0,1,254,248,0,1,255,76,0,1,255,160,0,1,255,232,0,2,0,48,0,2,0,120,0,2,0,192,0,2,0,252,0,2,1,60,0,2,1,160,0,2,2,28,0,2,2,128,0,2,2,192,0,2,3,0,0,2,3,64,0,2,3,128,0,2,3,220,0,2,4,56,0,2,4,120,0,2,4,184,0,2,4,248,0,2,5,56,0,2, +5,120,0,2,5,184,0,2,6,12,0,2,6,100,0,2,6,180,0,2,7,4,0,2,7,76,0,2,7,152,0,2,7,224,0,2,8,44,0,2,8,104,0,2,8,164,0,2,8,228,0,2,9,32,0,2,9,92,0,2,9,152,0,2,9,240,0,2,10,64,0,2,10,160,0,2,11,0,0,2,11,88,0,2,11,200,0,2,12,28,0,2,12,96,0,2,12,164,0,2,12,244, +0,2,13,148,0,2,13,228,0,2,14,64,0,2,14,132,0,2,14,200,0,2,15,32,0,2,15,112,0,2,15,192,0,2,16,40,0,2,16,92,0,2,16,144,0,2,16,224,0,2,17,24,0,2,17,116,0,2,18,12,0,2,18,60,0,2,18,164,0,2,19,112,0,2,19,236,0,2,20,24,0,2,20,116,0,2,21,4,0,2,21,152,0,2,21, +244,0,2,22,132,0,2,22,212,0,2,22,240,0,2,23,56,0,2,23,96,0,2,23,208,0,2,23,252,0,2,24,60,0,2,24,76,0,2,24,96,0,2,24,116,0,2,24,132,0,2,24,232,0,2,25,0,0,2,25,24,0,2,25,144,0,2,26,84,0,2,26,120,0,2,26,160,0,2,26,176,0,2,26,216,0,2,27,0,0,2,27,116,0,2, +27,236,0,2,28,92,0,2,28,244,0,2,29,204,0,2,29,240,0,2,30,20,0,2,30,48,0,2,30,92,0,2,30,116,0,2,30,172,0,2,30,220,0,2,30,252,0,2,31,88,0,2,31,180,0,2,32,32,0,2,32,128,0,2,32,232,0,2,33,108,0,2,33,228,0,2,34,124,0,2,35,20,0,2,36,8,0,2,36,180,0,2,37,108, +0,2,38,96,0,2,38,216,0,2,39,36,0,2,39,224,0,2,40,84,0,2,40,108,0,2,40,148,0,2,40,180,0,2,40,212,0,2,41,20,0,2,41,92,0,2,41,184,0,2,42,36,0,2,42,108,0,2,42,172,0,2,42,236,0,2,43,56,0,2,43,128,0,2,44,100,0,2,44,232,0,2,45,116,0,2,45,248,0,2,46,44,0,2,46, +136,0,2,46,200,0,2,47,40,0,2,47,132,0,2,47,200,0,2,48,8,0,2,48,104,0,2,48,204,0,2,49,52,0,2,49,136,0,2,49,220,0,2,50,68,0,2,50,168,0,2,51,32,0,2,51,168,0,2,52,72,0,2,52,244,0,2,53,56,0,2,53,124,0,2,54,0,0,2,54,136,0,2,54,196,0,2,54,252,0,2,55,100,0,2, +55,204,0,2,56,96,0,2,56,240,0,2,57,88,0,2,57,192,0,2,58,8,0,2,58,76,0,2,58,184,0,2,59,36,0,2,59,120,0,2,59,200,0,2,60,68,0,2,60,208,0,2,61,56,0,2,61,164,0,2,61,240,0,2,62,76,0,2,62,164,0,2,62,252,0,2,63,120,0,2,63,248,0,2,64,32,0,2,64,68,0,2,65,12,0, +2,65,188,0,2,66,136,0,2,67,60,0,2,67,236,0,2,68,212,0,2,69,196,0,2,70,132,0,2,71,56,0,2,71,136,0,2,71,192,0,2,72,32,0,2,72,88,0,2,72,128,0,2,72,164,0,2,72,200,0,2,72,240,0,2,73,32,0,2,73,76,0,2,73,136,0,2,73,192,0,2,74,16,0,2,74,80,0,2,74,144,0,2,74, +196,0,2,74,244,0,2,75,36,0,2,75,140,0,2,75,196,0,2,76,0,0,2,76,120,0,2,76,240,0,2,77,64,0,2,77,148,0,2,77,204,0,2,78,0,0,2,78,104,0,2,78,208,0,2,79,104,0,2,79,252,0,2,80,80,0,2,80,160,0,2,80,236,0,2,81,56,0,2,81,180,0,2,82,56,0,2,82,220,0,2,83,124,0, +2,83,144,0,2,83,160,0,2,83,204,0,2,84,4,0,2,84,44,0,2,84,84,0,2,84,136,0,2,84,200,0,2,84,232,0,2,85,8,0,2,85,40,0,2,85,72,0,2,85,112,0,2,85,152,0,2,85,192,0,2,85,232,0,2,86,8,0,2,86,92,0,2,86,108,0,2,86,176,0,2,86,244,0,2,87,76,0,2,88,52,0,2,88,88,0, +2,88,124,0,2,88,156,0,2,88,188,0,2,88,220,0,2,89,52,0,2,89,140,0,2,89,196,0,2,90,40,0,2,90,128,0,2,95,44,0,2,95,144,0,2,95,184,0,2,95,232,0,2,96,20,0,2,96,88,0,2,96,168,0,2,97,4,0,2,97,28,0,2,97,168,0,2,98,44,0,2,98,68,0,2,98,124,0,2,98,180,0,2,98,236, +0,2,99,32,0,2,99,108,0,2,99,184,0,2,99,252,0,2,100,68,0,2,100,144,0,2,100,224,0,2,101,112,0,2,101,164,0,2,101,244,0,2,102,60,0,2,102,140,0,2,102,252,0,2,103,68,0,2,103,148,0,2,103,200,0,2,104,20,0,2,104,96,0,2,104,176,0,2,105,32,0,2,105,104,0,2,105,184, +0,2,105,208,0,2,105,232,0,2,106,0,0,2,106,24,0,2,106,48,0,2,106,168,0,2,106,192,0,2,106,216,0,2,106,240,0,2,107,48,0,2,107,116,0,2,107,140,0,2,107,164,0,2,107,192,0,2,108,76,0,2,108,176,0,2,108,200,0,2,108,224,0,2,109,16,0,2,109,172,0,2,110,120,0,2,110, +220,0,2,111,28,0,2,111,132,0,2,111,156,0,2,112,8,0,2,112,112,0,2,112,128,0,2,112,144,0,2,112,160,0,2,112,184,0,2,112,208,0,2,112,232,0,2,113,0,0,2,113,16,0,2,113,96,0,2,113,248,0,2,114,164,0,2,115,164,0,2,116,116,0,2,117,164,0,2,118,72,0,2,118,244,0, +2,119,116,0,2,119,160,0,2,119,216,0,2,119,244,0,2,120,44,0,2,120,100,0,2,120,128,0,2,120,184,0,2,120,216,0,2,120,244,0,2,121,24,0,2,121,60,0,2,121,88,0,2,121,120,0,2,121,172,0,2,122,4,0,2,122,60,0,2,122,88,0,2,122,144,0,2,122,232,0,2,123,28,0,2,123,56, +0,2,123,132,0,2,123,176,0,2,123,244,0,2,124,16,0,2,124,44,0,2,124,72,0,2,124,100,0,2,124,152,0,2,124,208,0,2,125,8,0,2,125,68,0,2,125,124,0,2,125,188,0,2,126,4,0,2,126,80,0,2,126,116,0,2,126,152,0,2,126,188,0,2,126,224,0,2,127,4,0,2,127,40,0,2,127,76, +0,2,127,112,0,2,127,144,0,2,127,180,0,2,127,216,0,2,127,252,0,2,128,28,0,2,128,60,0,2,128,92,0,2,128,128,0,2,128,168,0,2,128,208,0,2,128,252,0,2,129,40,0,2,129,80,0,2,129,128,0,2,129,172,0,2,129,212,0,2,129,252,0,2,130,36,0,2,130,80,0,2,130,124,0,2,130, +164,0,2,130,212,0,2,131,0,0,2,131,40,0,2,131,80,0,2,131,124,0,2,131,168,0,2,131,208,0,2,131,248,0,2,132,36,0,2,132,80,0,2,132,120,0,2,132,156,0,2,132,200,0,2,132,244,0,2,133,28,0,2,133,68,0,2,133,112,0,2,133,156,0,2,133,196,0,2,133,244,0,2,134,40,0,2, +134,92,0,2,134,144,0,2,134,196,0,2,134,248,0,2,135,44,0,2,135,100,0,2,135,156,0,2,135,212,0,2,136,12,0,2,136,64,0,2,136,116,0,2,136,168,0,2,136,220,0,2,137,16,0,2,137,52,0,2,137,96,0,2,137,140,0,2,137,184,0,2,137,224,0,2,138,8,0,2,138,52,0,2,138,96,0, +2,138,148,0,2,138,192,0,2,138,236,0,2,139,32,0,2,139,76,0,2,139,120,0,2,139,172,0,2,139,216,0,2,140,4,0,2,140,56,0,2,140,104,0,2,140,156,0,2,140,224,0,2,141,16,0,2,141,68,0,2,141,132,0,2,141,184,0,2,141,232,0,2,142,40,0,2,142,92,0,2,142,140,0,2,142,204, +0,2,143,20,0,2,143,88,0,2,143,180,0,2,143,228,0,2,144,20,0,2,144,68,0,2,144,116,0,2,144,148,0,2,144,176,0,2,144,240,0,2,145,12,0,2,145,40,0,2,145,68,0,2,145,96,0,2,145,124,0,2,145,152,0,2,145,180,0,2,145,208,0,2,145,244,0,2,146,28,0,2,146,64,0,2,146, +104,0,2,146,124,0,2,146,152,0,2,146,180,0,2,146,208,0,2,146,236,0,2,147,8,0,2,147,36,0,2,147,64,0,2,147,92,0,2,147,120,0,2,147,148,0,2,147,176,0,2,147,204,0,2,147,232,0,2,148,4,0,2,148,32,0,2,148,52,0,2,148,252,0,2,150,100,0,2,151,44,0,2,151,64,0,2,151, +84,0,2,151,112,0,2,151,132,0,2,151,152,0,2,151,188,0,2,151,212,0,2,151,248,0,2,152,28,0,2,152,48,0,2,152,72,0,2,152,108,0,2,152,136,0,2,152,180,0,2,153,8,0,2,153,32,0,2,153,120,0,2,153,212,0,2,155,8,0,2,155,144,0,2,156,24,0,2,157,184,0,2,157,212,0,2, +158,0,0,2,158,28,0,2,158,72,0,2,158,100,0,2,158,144,0,2,158,176,0,2,158,224,0,2,158,252,0,2,159,36,0,2,159,64,0,2,159,108,0,2,159,136,0,2,159,180,0,2,159,208,0,2,159,252,0,2,160,24,0,2,160,64,0,2,160,92,0,2,160,136,0,2,160,164,0,2,160,204,0,2,160,232, +0,2,161,20,0,2,161,48,0,2,161,88,0,2,161,116,0,2,161,156,0,2,161,188,0,2,161,240,0,2,162,52,0,2,162,192,0,2,163,20,0,2,163,120,0,2,164,112,0,2,165,36,0,2,165,216,0,2,166,16,0,2,166,100,0,2,166,184,0,2,167,16,0,2,167,104,0,2,167,204,0,2,168,28,0,2,168, +68,0,2,168,108,0,2,168,172,0,2,169,32,0,2,169,112,0,2,169,196,0,2,169,244,0,2,170,32,0,2,170,76,0,2,170,120,0,2,170,188,0,2,171,0,0,2,171,28,0,2,171,56,0,2,171,80,0,2,171,104,0,2,171,180,0,2,171,224,0,2,172,12,0,2,172,52,0,2,172,92,0,2,172,152,0,2,172, +228,0,2,173,16,0,2,173,56,0,2,173,156,0,2,173,220,0,2,174,24,0,2,174,88,0,2,174,152,0,2,175,12,0,2,175,128,0,2,175,248,0,2,176,112,0,2,176,152,0,2,176,192,0,2,176,232,0,2,177,20,0,2,177,48,0,2,177,92,0,2,177,120,0,2,177,160,0,2,178,144,0,2,178,252,0, +2,179,176,0,2,183,188,0,2,186,124,0,2,186,176,0,2,187,12,0,2,187,92,0,2,187,188,0,2,188,68,0,2,189,12,0,2,189,212,0,2,190,56,0,2,190,212,0,2,193,8,0,2,195,172,0,2,195,228,0,2,196,92,0,2,196,208,0,2,197,40,0,2,198,128,0,2,200,24,0,2,200,96,0,2,200,148, +0,2,201,96,0,2,202,36,0,2,202,188,0,2,203,84,0,2,204,24,0,2,204,224,0,2,205,164,0,2,206,104,0,2,209,216,0,2,210,84,0,2,211,108,0,2,212,192,0,2,215,232,0,2,216,100,0,2,216,236,0,2,217,92,0,2,217,192,0,2,218,68,0,2,218,212,0,2,220,20,0,2,221,56,0,2,221, +208,0,2,222,92,0,2,223,4,0,2,224,116,0,2,225,48,0,2,225,240,0,2,226,132,0,2,227,156,0,2,228,48,0,2,228,196,0,2,229,132,0,2,230,4,0,2,230,128,0,2,231,12,0,2,231,108,0,2,231,208,0,2,232,112,0,2,233,28,0,2,233,128,0,2,233,236,0,2,234,124,0,2,234,220,0,2, +235,148,0,2,236,80,0,2,237,20,0,2,237,132,0,2,238,36,0,2,238,108,0,2,239,4,0,2,239,200,0,2,240,68,0,2,241,108,0,2,243,144,0,2,244,40,0,2,245,68,0,2,246,88,0,2,247,104,0,2,248,244,0,2,249,236,0,2,250,108,0,2,251,48,0,2,251,248,0,2,252,136,0,2,252,248, +0,2,253,152,0,2,253,224,0,2,254,128,0,2,255,68,0,2,255,152,0,2,255,200,0,3,0,232,0,3,1,204,0,3,2,12,0,3,2,104,0,3,2,204,0,3,3,44,0,3,3,124,0,3,3,204,0,3,4,96,0,3,5,32,0,3,6,4,0,3,7,252,0,3,8,224,0,3,9,240,0,3,11,24,0,3,12,4,0,3,13,20,0,3,14,52,0,3,15, +16,0,3,15,208,0,3,16,212,0,3,18,4,0,3,19,80,0,3,20,68,0,3,20,220,0,3,21,76,0,3,22,4,0,3,22,252,0,3,24,60,0,3,25,192,0,3,27,136,0,3,28,28,0,3,28,212,0,3,29,60,0,3,29,200,0,3,29,228,0,3,30,12,0,3,30,108,0,3,30,172,0,3,31,32,0,3,32,20,0,3,33,72,0,3,34,92, +0,3,35,4,0,3,35,128,0,3,36,32,0,3,37,32,0,3,38,236,0,3,41,128,0,3,43,44,0,3,43,176,0,3,43,252,0,3,44,36,0,3,44,108,0,3,46,48,0,3,47,204,0,3,49,136,0,3,53,64,0,3,54,232,0,3,56,140,0,3,57,20,0,3,57,188,0,3,60,96,0,3,61,252,0,3,63,44,0,3,64,40,0,3,65,84, +0,3,66,52,0,3,66,184,0,3,67,28,0,3,67,128,0,3,67,196,0,3,68,8,0,3,68,208,0,3,69,196,0,3,70,68,0,3,70,120,0,3,70,180,0,3,70,248,0,3,71,40,0,3,71,136,0,3,71,248,0,3,72,224,0,3,73,112,0,3,74,44,0,3,75,172,0,3,77,116,0,3,80,204,0,3,81,52,0,3,81,248,0,3,82, +92,0,3,82,240,0,3,83,128,0,3,84,60,0,3,84,188,0,3,85,48,0,3,85,168,0,3,86,16,0,3,86,92,0,3,86,188,0,3,87,32,0,3,87,120,0,3,88,40,0,3,88,108,0,3,88,188,0,3,89,12,0,3,89,116,0,3,90,32,0,3,91,212,0,3,93,212,0,3,95,20,0,3,97,68,0,3,98,224,0,3,101,172,0,3, +107,168,0,3,109,4,0,3,111,84,0,3,112,20,0,3,112,204,0,3,113,144,0,3,115,16,0,3,116,140,0,3,117,224,0,3,119,48,0,3,120,116,0,3,120,236,0,3,121,32,0,3,121,84,0,3,121,132,0,3,121,180,0,3,122,12,0,3,122,40,0,3,122,68,0,3,122,96,0,3,122,132,0,3,122,168,0, +3,122,196,0,3,122,224,0,3,123,216,0,3,124,132,0,3,125,88,0,3,125,212,0,3,126,84,0,3,127,116,0,3,128,88,0,3,128,196,0,3,129,48,0,3,129,108,0,3,129,172,0,3,129,212,0,3,129,252,0,3,130,36,0,3,130,76,0,3,130,116,0,3,130,156,0,3,130,196,0,3,130,236,0,3,131, +80,0,3,131,192,0,3,131,240,0,3,132,28,0,3,132,72,0,3,132,116,0,3,132,164,0,3,133,72,0,3,133,112,0,3,133,152,0,3,133,232,0,3,134,56,0,3,134,96,0,3,134,144,0,3,134,192,0,3,134,228,0,3,135,56,0,3,135,140,0,3,135,184,0,3,135,228,0,3,136,40,0,3,136,108,0, +3,136,188,0,3,137,8,0,3,137,84,0,3,137,160,0,3,137,244,0,3,138,72,0,3,138,188,0,3,139,88,0,3,139,176,0,3,139,248,0,3,140,80,0,3,140,248,0,3,141,144,0,3,142,52,0,3,143,16,0,3,143,172,0,3,144,216,0,3,146,12,0,3,146,164,0,3,146,180,0,3,147,20,0,3,147,116, +0,3,147,196,0,3,148,0,0,3,148,52,0,3,148,104,0,3,148,144,0,3,148,184,0,3,148,212,0,3,148,240,0,3,149,32,0,3,149,84,0,3,149,156,0,3,149,224,0,3,150,36,0,3,150,84,0,3,150,132,0,3,150,164,0,3,150,232,0,3,151,60,0,3,151,140,0,3,151,156,0,3,151,180,0,3,151, +212,0,3,151,252,0,3,152,36,0,3,152,76,0,3,152,120,0,3,152,164,0,3,152,208,0,3,152,252,0,3,153,48,0,3,153,100,0,3,153,144,0,3,153,188,0,3,153,228,0,3,154,12,0,3,154,60,0,3,154,108,0,3,154,156,0,3,154,204,0,3,155,112,0,3,155,236,0,3,156,96,0,3,156,180, +0,3,156,236,0,3,157,96,0,3,157,132,0,3,157,172,0,3,158,44,0,3,158,124,0,3,158,240,0,3,159,4,0,3,159,44,0,3,159,212,0,3,160,44,0,3,160,168,0,3,160,192,0,3,160,224,0,3,161,0,0,3,161,32,0,3,161,64,0,3,161,80,0,3,161,120,0,3,161,160,0,3,161,200,0,3,161,240, +0,3,162,24,0,3,162,64,0,3,162,104,0,3,162,144,0,3,162,184,0,3,162,220,0,3,162,252,0,3,163,32,0,3,163,68,0,3,163,104,0,3,163,136,0,3,163,180,0,3,163,224,0,3,164,12,0,3,164,56,0,3,164,76,0,3,164,144,0,3,164,212,0,3,165,4,0,3,165,52,0,3,165,128,0,3,165, +220,0,3,165,236,0,3,166,20,0,3,166,56,0,3,166,104,0,3,166,120,0,3,166,216,0,3,167,16,0,3,167,92,0,3,167,160,0,3,167,236,0,3,168,148,0,3,169,12,0,3,169,172,0,3,170,52,0,3,170,76,0,3,170,100,0,3,170,124,0,3,170,148,0,3,170,172,0,3,170,196,0,3,170,220,0, +3,170,244,0,3,171,12,0,3,171,36,0,3,171,60,0,3,171,84,0,3,171,108,0,3,171,132,0,3,171,156,0,3,171,180,0,3,171,204,0,3,171,228,0,3,171,252,0,3,172,20,0,3,172,44,0,3,172,68,0,3,172,92,0,3,172,116,0,3,172,140,0,3,172,164,0,3,172,188,0,3,172,212,0,3,172, +236,0,3,173,4,0,3,173,28,0,3,173,52,0,3,173,76,0,3,173,100,0,3,173,124,0,3,173,148,0,3,173,172,0,3,173,196,0,3,173,220,0,3,173,244,0,3,174,12,0,3,174,36,0,3,174,60,0,3,174,84,0,3,174,108,0,3,174,132,0,3,174,156,0,3,174,180,0,3,174,204,0,3,174,228,0,3, +174,252,0,3,175,20,0,3,175,36,0,3,175,192,0,3,175,208,0,3,175,224,0,3,175,248,0,3,176,16,0,3,176,40,0,3,176,64,0,3,176,80,0,3,176,200,0,3,176,216,0,3,177,168,0,3,177,184,0,3,178,108,0,3,178,160,0,3,178,228,0,3,178,244,0,3,179,4,0,3,179,28,0,3,179,52, +0,3,179,68,0,3,179,92,0,3,179,108,0,3,179,160,0,3,179,176,0,3,179,192,0,3,179,216,0,3,179,232,0,3,180,0,0,3,180,16,0,3,180,40,0,3,180,56,0,3,180,80,0,3,180,96,0,3,180,120,0,3,180,136,0,3,180,160,0,3,180,184,0,3,180,208,0,3,180,232,0,3,181,0,0,3,181,24, +0,3,181,48,0,3,181,72,0,3,181,96,0,3,181,120,0,3,181,144,0,3,181,168,0,3,181,184,0,3,181,236,0,3,182,4,0,3,182,28,0,3,182,52,0,3,182,76,0,3,182,100,0,3,182,124,0,3,182,148,0,3,182,172,0,3,182,196,0,3,182,220,0,3,182,244,0,3,183,12,0,3,183,36,0,3,183, +60,0,3,183,84,0,3,183,108,0,3,183,132,0,3,183,156,0,3,183,172,0,3,184,68,0,3,184,172,0,3,185,48,0,3,185,72,0,3,185,96,0,3,185,120,0,3,185,144,0,3,185,160,0,3,186,8,0,3,186,32,0,3,186,56,0,3,186,72,0,3,186,160,0,3,186,184,0,3,186,208,0,3,186,224,0,3,187, +180,0,3,188,68,0,3,188,228,0,3,188,252,0,3,189,20,0,3,189,44,0,3,189,68,0,3,189,84,0,3,190,36,0,3,190,168,0,3,191,68,0,3,191,92,0,3,191,116,0,3,191,140,0,3,191,164,0,3,191,180,0,3,192,44,0,3,192,144,0,3,193,8,0,3,193,32,0,3,193,56,0,3,193,80,0,3,193, +104,0,3,193,120,0,3,194,36,0,3,194,124,0,3,195,12,0,3,195,36,0,3,195,60,0,3,195,84,0,3,195,108,0,3,195,132,0,3,195,156,0,3,195,180,0,3,195,204,0,3,195,228,0,3,195,252,0,3,196,20,0,3,196,44,0,3,196,60,0,3,197,8,0,3,197,116,0,3,197,252,0,3,198,12,0,3,198, +128,0,3,198,184,0,3,199,0,0,3,199,16,0,3,199,172,0,3,200,48,0,3,200,192,0,3,200,216,0,3,200,240,0,3,201,8,0,3,201,32,0,3,201,48,0,3,201,168,0,3,202,100,0,3,202,244,0,3,203,4,0,3,203,152,0,3,203,168,0,3,204,76,0,3,204,100,0,3,204,124,0,3,204,148,0,3,204, +172,0,3,204,196,0,3,204,220,0,3,204,244,0,3,205,12,0,3,205,36,0,3,205,60,0,3,205,144,0,3,205,248,0,3,205,248,0,3,205,248,0,3,205,248,0,3,205,248,0,3,205,248,0,3,206,136,0,3,206,208,0,3,206,224,0,3,206,240,0,3,207,0,0,3,207,16,0,3,207,32,0,3,207,48,0, +3,207,64,0,3,207,80,0,3,207,96,0,3,207,112,0,3,207,128,0,3,207,144,0,3,207,160,0,3,207,176,0,3,207,192,0,3,207,208,0,3,207,224,0,3,207,240,0,3,208,0,0,3,208,16,0,3,208,32,0,3,208,48,0,3,208,64,0,3,208,80,0,3,208,96,0,3,208,112,0,3,208,128,0,3,208,144, +0,3,208,160,0,3,208,176,0,3,208,192,0,3,208,208,0,3,208,224,0,3,208,240,0,3,209,0,0,3,209,16,0,3,209,32,0,3,209,48,0,3,209,64,0,3,209,80,0,3,209,96,0,3,209,112,0,3,209,128,0,3,209,144,0,3,209,160,0,3,209,176,0,3,209,192,0,3,209,208,0,3,209,224,0,3,209, +240,0,3,210,0,0,3,210,16,0,3,210,32,0,3,210,48,0,3,210,64,0,3,210,80,0,3,210,96,0,3,210,112,0,3,210,128,0,3,210,144,0,3,210,160,0,3,210,176,0,3,210,220,0,3,211,84,0,3,211,220,0,3,213,8,0,3,213,144,0,3,214,16,0,3,214,160,0,3,214,216,0,3,215,12,0,3,215, +96,0,3,215,140,0,3,215,208,0,3,215,252,0,3,216,128,0,3,216,172,0,3,216,200,0,3,216,228,0,3,217,0,0,3,217,72,0,3,217,112,0,3,217,136,0,3,217,172,0,3,217,220,0,3,218,80,0,3,218,236,0,3,219,136,0,3,220,76,0,3,221,4,0,3,221,52,0,3,221,88,0,3,221,144,0,3, +221,176,0,3,221,208,0,3,222,32,0,3,222,172,0,3,223,0,0,3,223,176,0,3,223,208,0,3,223,232,0,3,224,0,0,3,224,24,0,3,224,48,0,3,224,72,0,3,224,248,0,3,225,16,0,3,225,112,0,3,225,136,0,3,225,160,0,3,225,176,0,3,226,0,0,3,226,244,0,3,227,8,0,1,0,0,13,49,2, +12,0,43,0,107,0,6,0,2,0,16,0,153,0,8,0,0,5,87,1,17,0,5,0,4,0,0,0,22,1,14,0,1,0,0,0,0,0,0,0,95,0,192,0,1,0,0,0,0,0,1,0,16,1,66,0,1,0,0,0,0,0,2,0,4,1,93,0,1,0,0,0,0,0,3,0,16,1,132,0,1,0,0,0,0,0,4,0,16,1,183,0,1,0,0,0,0,0,5,0,12,1,226,0,1,0,0,0,0,0,6,0, +14,2,13,0,1,0,0,0,0,0,8,0,17,2,64,0,1,0,0,0,0,0,11,0,29,2,142,0,1,0,0,0,0,0,13,9,147,21,212,0,1,0,0,0,0,0,14,0,52,31,210,0,3,0,1,4,9,0,0,0,190,0,0,0,3,0,1,4,9,0,1,0,32,1,32,0,3,0,1,4,9,0,2,0,8,1,83,0,3,0,1,4,9,0,3,0,32,1,98,0,3,0,1,4,9,0,4,0,32,1,149, +0,3,0,1,4,9,0,5,0,24,1,200,0,3,0,1,4,9,0,6,0,28,1,239,0,3,0,1,4,9,0,8,0,34,2,28,0,3,0,1,4,9,0,11,0,58,2,82,0,3,0,1,4,9,0,13,19,38,2,172,0,3,0,1,4,9,0,14,0,104,31,104,0,67,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,40,0,99,0,41,0,32,0,50,0, +48,0,48,0,51,0,32,0,98,0,121,0,32,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,44,0,32,0,73,0,110,0,99,0,46,0,32,0,65,0,108,0,108,0,32,0,82,0,105,0,103,0,104,0,116,0,115,0,32,0,82,0,101,0,115,0,101,0,114,0,118,0,101,0,100,0,46,0,10,0,68,0,101, +0,106,0,97,0,86,0,117,0,32,0,99,0,104,0,97,0,110,0,103,0,101,0,115,0,32,0,97,0,114,0,101,0,32,0,105,0,110,0,32,0,112,0,117,0,98,0,108,0,105,0,99,0,32,0,100,0,111,0,109,0,97,0,105,0,110,0,10,0,0,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48, +48,51,32,98,121,32,66,105,116,115,116,114,101,97,109,44,32,73,110,99,46,32,65,108,108,32,82,105,103,104,116,115,32,82,101,115,101,114,118,101,100,46,10,68,101,106,97,86,117,32,99,104,97,110,103,101,115,32,97,114,101,32,105,110,32,112,117,98,108,105,99, +32,100,111,109,97,105,110,10,0,0,68,0,101,0,106,0,97,0,86,0,117,0,32,0,83,0,97,0,110,0,115,0,32,0,77,0,111,0,110,0,111,0,0,68,101,106,97,86,117,32,83,97,110,115,32,77,111,110,111,0,0,66,0,111,0,111,0,107,0,0,66,111,111,107,0,0,68,0,101,0,106,0,97,0,86, +0,117,0,32,0,83,0,97,0,110,0,115,0,32,0,77,0,111,0,110,0,111,0,0,68,101,106,97,86,117,32,83,97,110,115,32,77,111,110,111,0,0,68,0,101,0,106,0,97,0,86,0,117,0,32,0,83,0,97,0,110,0,115,0,32,0,77,0,111,0,110,0,111,0,0,68,101,106,97,86,117,32,83,97,110,115, +32,77,111,110,111,0,0,86,0,101,0,114,0,115,0,105,0,111,0,110,0,32,0,50,0,46,0,51,0,55,0,0,86,101,114,115,105,111,110,32,50,46,51,55,0,0,68,0,101,0,106,0,97,0,86,0,117,0,83,0,97,0,110,0,115,0,77,0,111,0,110,0,111,0,0,68,101,106,97,86,117,83,97,110,115, +77,111,110,111,0,0,68,0,101,0,106,0,97,0,86,0,117,0,32,0,102,0,111,0,110,0,116,0,115,0,32,0,116,0,101,0,97,0,109,0,0,68,101,106,97,86,117,32,102,111,110,116,115,32,116,101,97,109,0,0,104,0,116,0,116,0,112,0,58,0,47,0,47,0,100,0,101,0,106,0,97,0,118,0, +117,0,46,0,115,0,111,0,117,0,114,0,99,0,101,0,102,0,111,0,114,0,103,0,101,0,46,0,110,0,101,0,116,0,0,104,116,116,112,58,47,47,100,101,106,97,118,117,46,115,111,117,114,99,101,102,111,114,103,101,46,110,101,116,0,0,70,0,111,0,110,0,116,0,115,0,32,0,97, +0,114,0,101,0,32,0,40,0,99,0,41,0,32,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,32,0,40,0,115,0,101,0,101,0,32,0,98,0,101,0,108,0,111,0,119,0,41,0,46,0,32,0,68,0,101,0,106,0,97,0,86,0,117,0,32,0,99,0,104,0,97,0,110,0,103,0,101,0,115,0,32,0, +97,0,114,0,101,0,32,0,105,0,110,0,32,0,112,0,117,0,98,0,108,0,105,0,99,0,32,0,100,0,111,0,109,0,97,0,105,0,110,0,46,0,10,0,10,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,32,0,86,0,101,0,114,0,97,0,32,0,70,0,111,0,110,0,116,0,115,0,32,0,67,0, +111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,10,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,10,0,10,0,67,0,111,0,112,0,121,0,114,0,105,0,103, +0,104,0,116,0,32,0,40,0,99,0,41,0,32,0,50,0,48,0,48,0,51,0,32,0,98,0,121,0,32,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,44,0,32,0,73,0,110,0,99,0,46,0,32,0,65,0,108,0,108,0,32,0,82,0,105,0,103,0,104,0,116,0,115,0,32,0,82,0,101,0,115,0,101, +0,114,0,118,0,101,0,100,0,46,0,32,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,32,0,86,0,101,0,114,0,97,0,32,0,105,0,115,0,32,0,97,0,32,0,116,0,114,0,97,0,100,0,101,0,109,0,97,0,114,0,107,0,32,0,111,0,102,0,32,0,66,0,105,0,116,0,115,0,116,0, +114,0,101,0,97,0,109,0,44,0,32,0,73,0,110,0,99,0,46,0,10,0,10,0,80,0,101,0,114,0,109,0,105,0,115,0,115,0,105,0,111,0,110,0,32,0,105,0,115,0,32,0,104,0,101,0,114,0,101,0,98,0,121,0,32,0,103,0,114,0,97,0,110,0,116,0,101,0,100,0,44,0,32,0,102,0,114,0,101, +0,101,0,32,0,111,0,102,0,32,0,99,0,104,0,97,0,114,0,103,0,101,0,44,0,32,0,116,0,111,0,32,0,97,0,110,0,121,0,32,0,112,0,101,0,114,0,115,0,111,0,110,0,32,0,111,0,98,0,116,0,97,0,105,0,110,0,105,0,110,0,103,0,32,0,97,0,32,0,99,0,111,0,112,0,121,0,32,0,111, +0,102,0,32,0,116,0,104,0,101,0,32,0,102,0,111,0,110,0,116,0,115,0,32,0,97,0,99,0,99,0,111,0,109,0,112,0,97,0,110,0,121,0,105,0,110,0,103,0,32,0,116,0,104,0,105,0,115,0,32,0,108,0,105,0,99,0,101,0,110,0,115,0,101,0,32,0,40,0,34,0,70,0,111,0,110,0,116, +0,115,0,34,0,41,0,32,0,97,0,110,0,100,0,32,0,97,0,115,0,115,0,111,0,99,0,105,0,97,0,116,0,101,0,100,0,32,0,100,0,111,0,99,0,117,0,109,0,101,0,110,0,116,0,97,0,116,0,105,0,111,0,110,0,32,0,102,0,105,0,108,0,101,0,115,0,32,0,40,0,116,0,104,0,101,0,32,0, +34,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,34,0,41,0,44,0,32,0,116,0,111,0,32,0,114,0,101,0,112,0,114,0,111,0,100,0,117,0,99,0,101,0,32,0,97,0,110,0,100,0,32,0,100,0,105,0,115,0,116,0,114,0,105,0,98,0,117,0,116,0,101, +0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,44,0,32,0,105,0,110,0,99,0,108,0,117,0,100,0,105,0,110,0,103,0,32,0,119,0,105,0,116,0,104,0,111,0,117,0,116,0,32,0,108,0,105,0,109,0,105,0,116,0,97, +0,116,0,105,0,111,0,110,0,32,0,116,0,104,0,101,0,32,0,114,0,105,0,103,0,104,0,116,0,115,0,32,0,116,0,111,0,32,0,117,0,115,0,101,0,44,0,32,0,99,0,111,0,112,0,121,0,44,0,32,0,109,0,101,0,114,0,103,0,101,0,44,0,32,0,112,0,117,0,98,0,108,0,105,0,115,0,104, +0,44,0,32,0,100,0,105,0,115,0,116,0,114,0,105,0,98,0,117,0,116,0,101,0,44,0,32,0,97,0,110,0,100,0,47,0,111,0,114,0,32,0,115,0,101,0,108,0,108,0,32,0,99,0,111,0,112,0,105,0,101,0,115,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116, +0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,44,0,32,0,97,0,110,0,100,0,32,0,116,0,111,0,32,0,112,0,101,0,114,0,109,0,105,0,116,0,32,0,112,0,101,0,114,0,115,0,111,0,110,0,115,0,32,0,116,0,111,0,32,0,119,0,104,0,111,0,109,0,32,0,116,0,104,0,101, +0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,105,0,115,0,32,0,102,0,117,0,114,0,110,0,105,0,115,0,104,0,101,0,100,0,32,0,116,0,111,0,32,0,100,0,111,0,32,0,115,0,111,0,44,0,32,0,115,0,117,0,98,0,106,0,101,0,99, +0,116,0,32,0,116,0,111,0,32,0,116,0,104,0,101,0,32,0,102,0,111,0,108,0,108,0,111,0,119,0,105,0,110,0,103,0,32,0,99,0,111,0,110,0,100,0,105,0,116,0,105,0,111,0,110,0,115,0,58,0,10,0,10,0,84,0,104,0,101,0,32,0,97,0,98,0,111,0,118,0,101,0,32,0,99,0,111, +0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,97,0,110,0,100,0,32,0,116,0,114,0,97,0,100,0,101,0,109,0,97,0,114,0,107,0,32,0,110,0,111,0,116,0,105,0,99,0,101,0,115,0,32,0,97,0,110,0,100,0,32,0,116,0,104,0,105,0,115,0,32,0,112,0,101,0,114,0,109,0,105, +0,115,0,115,0,105,0,111,0,110,0,32,0,110,0,111,0,116,0,105,0,99,0,101,0,32,0,115,0,104,0,97,0,108,0,108,0,32,0,98,0,101,0,32,0,105,0,110,0,99,0,108,0,117,0,100,0,101,0,100,0,32,0,105,0,110,0,32,0,97,0,108,0,108,0,32,0,99,0,111,0,112,0,105,0,101,0,115, +0,32,0,111,0,102,0,32,0,111,0,110,0,101,0,32,0,111,0,114,0,32,0,109,0,111,0,114,0,101,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,116,0,121,0,112,0,101,0,102,0,97,0,99, +0,101,0,115,0,46,0,10,0,10,0,84,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,109,0,97,0,121,0,32,0,98,0,101,0,32,0,109,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,44,0,32,0,97,0,108,0,116,0,101,0,114, +0,101,0,100,0,44,0,32,0,111,0,114,0,32,0,97,0,100,0,100,0,101,0,100,0,32,0,116,0,111,0,44,0,32,0,97,0,110,0,100,0,32,0,105,0,110,0,32,0,112,0,97,0,114,0,116,0,105,0,99,0,117,0,108,0,97,0,114,0,32,0,116,0,104,0,101,0,32,0,100,0,101,0,115,0,105,0,103,0, +110,0,115,0,32,0,111,0,102,0,32,0,103,0,108,0,121,0,112,0,104,0,115,0,32,0,111,0,114,0,32,0,99,0,104,0,97,0,114,0,97,0,99,0,116,0,101,0,114,0,115,0,32,0,105,0,110,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,115,0,32,0,109,0,97,0,121,0,32,0,98, +0,101,0,32,0,109,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,32,0,97,0,110,0,100,0,32,0,97,0,100,0,100,0,105,0,116,0,105,0,111,0,110,0,97,0,108,0,32,0,103,0,108,0,121,0,112,0,104,0,115,0,32,0,111,0,114,0,32,0,32,0,111,0,114,0,32,0,99,0,104,0,97,0,114, +0,97,0,99,0,116,0,101,0,114,0,115,0,32,0,109,0,97,0,121,0,32,0,98,0,101,0,32,0,97,0,100,0,100,0,101,0,100,0,32,0,116,0,111,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,115,0,44,0,32,0,111,0,110,0,108,0,121,0,32,0,105,0,102,0,32,0,116,0,104,0, +101,0,32,0,102,0,111,0,110,0,116,0,115,0,32,0,97,0,114,0,101,0,32,0,114,0,101,0,110,0,97,0,109,0,101,0,100,0,32,0,116,0,111,0,32,0,110,0,97,0,109,0,101,0,115,0,32,0,110,0,111,0,116,0,32,0,99,0,111,0,110,0,116,0,97,0,105,0,110,0,105,0,110,0,103,0,32,0, +101,0,105,0,116,0,104,0,101,0,114,0,32,0,116,0,104,0,101,0,32,0,119,0,111,0,114,0,100,0,115,0,32,0,34,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,34,0,32,0,111,0,114,0,32,0,116,0,104,0,101,0,32,0,119,0,111,0,114,0,100,0,32,0,34,0,86,0,101,0, +114,0,97,0,34,0,46,0,10,0,10,0,84,0,104,0,105,0,115,0,32,0,76,0,105,0,99,0,101,0,110,0,115,0,101,0,32,0,98,0,101,0,99,0,111,0,109,0,101,0,115,0,32,0,110,0,117,0,108,0,108,0,32,0,97,0,110,0,100,0,32,0,118,0,111,0,105,0,100,0,32,0,116,0,111,0,32,0,116, +0,104,0,101,0,32,0,101,0,120,0,116,0,101,0,110,0,116,0,32,0,97,0,112,0,112,0,108,0,105,0,99,0,97,0,98,0,108,0,101,0,32,0,116,0,111,0,32,0,70,0,111,0,110,0,116,0,115,0,32,0,111,0,114,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0, +114,0,101,0,32,0,116,0,104,0,97,0,116,0,32,0,104,0,97,0,115,0,32,0,98,0,101,0,101,0,110,0,32,0,109,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,32,0,97,0,110,0,100,0,32,0,105,0,115,0,32,0,100,0,105,0,115,0,116,0,114,0,105,0,98,0,117,0,116,0,101,0,100, +0,32,0,117,0,110,0,100,0,101,0,114,0,32,0,116,0,104,0,101,0,32,0,34,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,32,0,86,0,101,0,114,0,97,0,34,0,32,0,110,0,97,0,109,0,101,0,115,0,46,0,10,0,10,0,84,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32, +0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,109,0,97,0,121,0,32,0,98,0,101,0,32,0,115,0,111,0,108,0,100,0,32,0,97,0,115,0,32,0,112,0,97,0,114,0,116,0,32,0,111,0,102,0,32,0,97,0,32,0,108,0,97,0,114,0,103,0,101,0,114,0,32,0,115,0,111,0,102,0,116, +0,119,0,97,0,114,0,101,0,32,0,112,0,97,0,99,0,107,0,97,0,103,0,101,0,32,0,98,0,117,0,116,0,32,0,110,0,111,0,32,0,99,0,111,0,112,0,121,0,32,0,111,0,102,0,32,0,111,0,110,0,101,0,32,0,111,0,114,0,32,0,109,0,111,0,114,0,101,0,32,0,111,0,102,0,32,0,116,0, +104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,116,0,121,0,112,0,101,0,102,0,97,0,99,0,101,0,115,0,32,0,109,0,97,0,121,0,32,0,98,0,101,0,32,0,115,0,111,0,108,0,100,0,32,0,98,0,121,0,32,0,105,0,116,0,115, +0,101,0,108,0,102,0,46,0,10,0,10,0,84,0,72,0,69,0,32,0,70,0,79,0,78,0,84,0,32,0,83,0,79,0,70,0,84,0,87,0,65,0,82,0,69,0,32,0,73,0,83,0,32,0,80,0,82,0,79,0,86,0,73,0,68,0,69,0,68,0,32,0,34,0,65,0,83,0,32,0,73,0,83,0,34,0,44,0,32,0,87,0,73,0,84,0,72,0, +79,0,85,0,84,0,32,0,87,0,65,0,82,0,82,0,65,0,78,0,84,0,89,0,32,0,79,0,70,0,32,0,65,0,78,0,89,0,32,0,75,0,73,0,78,0,68,0,44,0,32,0,69,0,88,0,80,0,82,0,69,0,83,0,83,0,32,0,79,0,82,0,32,0,73,0,77,0,80,0,76,0,73,0,69,0,68,0,44,0,32,0,73,0,78,0,67,0,76,0, +85,0,68,0,73,0,78,0,71,0,32,0,66,0,85,0,84,0,32,0,78,0,79,0,84,0,32,0,76,0,73,0,77,0,73,0,84,0,69,0,68,0,32,0,84,0,79,0,32,0,65,0,78,0,89,0,32,0,87,0,65,0,82,0,82,0,65,0,78,0,84,0,73,0,69,0,83,0,32,0,79,0,70,0,32,0,77,0,69,0,82,0,67,0,72,0,65,0,78,0, +84,0,65,0,66,0,73,0,76,0,73,0,84,0,89,0,44,0,32,0,70,0,73,0,84,0,78,0,69,0,83,0,83,0,32,0,70,0,79,0,82,0,32,0,65,0,32,0,80,0,65,0,82,0,84,0,73,0,67,0,85,0,76,0,65,0,82,0,32,0,80,0,85,0,82,0,80,0,79,0,83,0,69,0,32,0,65,0,78,0,68,0,32,0,78,0,79,0,78,0, +73,0,78,0,70,0,82,0,73,0,78,0,71,0,69,0,77,0,69,0,78,0,84,0,32,0,79,0,70,0,32,0,67,0,79,0,80,0,89,0,82,0,73,0,71,0,72,0,84,0,44,0,32,0,80,0,65,0,84,0,69,0,78,0,84,0,44,0,32,0,84,0,82,0,65,0,68,0,69,0,77,0,65,0,82,0,75,0,44,0,32,0,79,0,82,0,32,0,79,0, +84,0,72,0,69,0,82,0,32,0,82,0,73,0,71,0,72,0,84,0,46,0,32,0,73,0,78,0,32,0,78,0,79,0,32,0,69,0,86,0,69,0,78,0,84,0,32,0,83,0,72,0,65,0,76,0,76,0,32,0,66,0,73,0,84,0,83,0,84,0,82,0,69,0,65,0,77,0,32,0,79,0,82,0,32,0,84,0,72,0,69,0,32,0,71,0,78,0,79,0, +77,0,69,0,32,0,70,0,79,0,85,0,78,0,68,0,65,0,84,0,73,0,79,0,78,0,32,0,66,0,69,0,32,0,76,0,73,0,65,0,66,0,76,0,69,0,32,0,70,0,79,0,82,0,32,0,65,0,78,0,89,0,32,0,67,0,76,0,65,0,73,0,77,0,44,0,32,0,68,0,65,0,77,0,65,0,71,0,69,0,83,0,32,0,79,0,82,0,32,0, +79,0,84,0,72,0,69,0,82,0,32,0,76,0,73,0,65,0,66,0,73,0,76,0,73,0,84,0,89,0,44,0,32,0,73,0,78,0,67,0,76,0,85,0,68,0,73,0,78,0,71,0,32,0,65,0,78,0,89,0,32,0,71,0,69,0,78,0,69,0,82,0,65,0,76,0,44,0,32,0,83,0,80,0,69,0,67,0,73,0,65,0,76,0,44,0,32,0,73,0, +78,0,68,0,73,0,82,0,69,0,67,0,84,0,44,0,32,0,73,0,78,0,67,0,73,0,68,0,69,0,78,0,84,0,65,0,76,0,44,0,32,0,79,0,82,0,32,0,67,0,79,0,78,0,83,0,69,0,81,0,85,0,69,0,78,0,84,0,73,0,65,0,76,0,32,0,68,0,65,0,77,0,65,0,71,0,69,0,83,0,44,0,32,0,87,0,72,0,69,0, +84,0,72,0,69,0,82,0,32,0,73,0,78,0,32,0,65,0,78,0,32,0,65,0,67,0,84,0,73,0,79,0,78,0,32,0,79,0,70,0,32,0,67,0,79,0,78,0,84,0,82,0,65,0,67,0,84,0,44,0,32,0,84,0,79,0,82,0,84,0,32,0,79,0,82,0,32,0,79,0,84,0,72,0,69,0,82,0,87,0,73,0,83,0,69,0,44,0,32,0, +65,0,82,0,73,0,83,0,73,0,78,0,71,0,32,0,70,0,82,0,79,0,77,0,44,0,32,0,79,0,85,0,84,0,32,0,79,0,70,0,32,0,84,0,72,0,69,0,32,0,85,0,83,0,69,0,32,0,79,0,82,0,32,0,73,0,78,0,65,0,66,0,73,0,76,0,73,0,84,0,89,0,32,0,84,0,79,0,32,0,85,0,83,0,69,0,32,0,84,0, +72,0,69,0,32,0,70,0,79,0,78,0,84,0,32,0,83,0,79,0,70,0,84,0,87,0,65,0,82,0,69,0,32,0,79,0,82,0,32,0,70,0,82,0,79,0,77,0,32,0,79,0,84,0,72,0,69,0,82,0,32,0,68,0,69,0,65,0,76,0,73,0,78,0,71,0,83,0,32,0,73,0,78,0,32,0,84,0,72,0,69,0,32,0,70,0,79,0,78,0, +84,0,32,0,83,0,79,0,70,0,84,0,87,0,65,0,82,0,69,0,46,0,10,0,10,0,69,0,120,0,99,0,101,0,112,0,116,0,32,0,97,0,115,0,32,0,99,0,111,0,110,0,116,0,97,0,105,0,110,0,101,0,100,0,32,0,105,0,110,0,32,0,116,0,104,0,105,0,115,0,32,0,110,0,111,0,116,0,105,0,99, +0,101,0,44,0,32,0,116,0,104,0,101,0,32,0,110,0,97,0,109,0,101,0,115,0,32,0,111,0,102,0,32,0,71,0,110,0,111,0,109,0,101,0,44,0,32,0,116,0,104,0,101,0,32,0,71,0,110,0,111,0,109,0,101,0,32,0,70,0,111,0,117,0,110,0,100,0,97,0,116,0,105,0,111,0,110,0,44,0, +32,0,97,0,110,0,100,0,32,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,32,0,73,0,110,0,99,0,46,0,44,0,32,0,115,0,104,0,97,0,108,0,108,0,32,0,110,0,111,0,116,0,32,0,98,0,101,0,32,0,117,0,115,0,101,0,100,0,32,0,105,0,110,0,32,0,97,0,100,0,118,0, +101,0,114,0,116,0,105,0,115,0,105,0,110,0,103,0,32,0,111,0,114,0,32,0,111,0,116,0,104,0,101,0,114,0,119,0,105,0,115,0,101,0,32,0,116,0,111,0,32,0,112,0,114,0,111,0,109,0,111,0,116,0,101,0,32,0,116,0,104,0,101,0,32,0,115,0,97,0,108,0,101,0,44,0,32,0,117, +0,115,0,101,0,32,0,111,0,114,0,32,0,111,0,116,0,104,0,101,0,114,0,32,0,100,0,101,0,97,0,108,0,105,0,110,0,103,0,115,0,32,0,105,0,110,0,32,0,116,0,104,0,105,0,115,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,119, +0,105,0,116,0,104,0,111,0,117,0,116,0,32,0,112,0,114,0,105,0,111,0,114,0,32,0,119,0,114,0,105,0,116,0,116,0,101,0,110,0,32,0,97,0,117,0,116,0,104,0,111,0,114,0,105,0,122,0,97,0,116,0,105,0,111,0,110,0,32,0,102,0,114,0,111,0,109,0,32,0,116,0,104,0,101, +0,32,0,71,0,110,0,111,0,109,0,101,0,32,0,70,0,111,0,117,0,110,0,100,0,97,0,116,0,105,0,111,0,110,0,32,0,111,0,114,0,32,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,32,0,73,0,110,0,99,0,46,0,44,0,32,0,114,0,101,0,115,0,112,0,101,0,99,0,116,0, +105,0,118,0,101,0,108,0,121,0,46,0,32,0,70,0,111,0,114,0,32,0,102,0,117,0,114,0,116,0,104,0,101,0,114,0,32,0,105,0,110,0,102,0,111,0,114,0,109,0,97,0,116,0,105,0,111,0,110,0,44,0,32,0,99,0,111,0,110,0,116,0,97,0,99,0,116,0,58,0,32,0,102,0,111,0,110,0, +116,0,115,0,32,0,97,0,116,0,32,0,103,0,110,0,111,0,109,0,101,0,32,0,100,0,111,0,116,0,32,0,111,0,114,0,103,0,46,0,32,0,10,0,0,70,111,110,116,115,32,97,114,101,32,40,99,41,32,66,105,116,115,116,114,101,97,109,32,40,115,101,101,32,98,101,108,111,119,41, +46,32,68,101,106,97,86,117,32,99,104,97,110,103,101,115,32,97,114,101,32,105,110,32,112,117,98,108,105,99,32,100,111,109,97,105,110,46,10,10,66,105,116,115,116,114,101,97,109,32,86,101,114,97,32,70,111,110,116,115,32,67,111,112,121,114,105,103,104,116, +10,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,48,51,32,98,121,32,66,105,116,115,116,114,101,97,109,44,32,73,110,99,46,32,65,108,108,32,82,105, +103,104,116,115,32,82,101,115,101,114,118,101,100,46,32,66,105,116,115,116,114,101,97,109,32,86,101,114,97,32,105,115,32,97,32,116,114,97,100,101,109,97,114,107,32,111,102,32,66,105,116,115,116,114,101,97,109,44,32,73,110,99,46,10,10,80,101,114,109,105, +115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111, +112,121,32,111,102,32,116,104,101,32,102,111,110,116,115,32,97,99,99,111,109,112,97,110,121,105,110,103,32,116,104,105,115,32,108,105,99,101,110,115,101,32,40,34,70,111,110,116,115,34,41,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111, +99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,70,111,110,116,32,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,114,101,112,114,111,100,117,99,101,32,97,110,100,32,100,105,115,116,114,105,98,117,116,101, +32,116,104,101,32,70,111,110,116,32,83,111,102,116,119,97,114,101,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,32,116,111,32,117,115,101,44, +32,99,111,112,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,97,110,100,47,111,114,32,115,101,108,108,32,99,111,112,105,101,115,32,111,102,32,116,104,101,32,70,111,110,116,32,83,111,102, +116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,70,111,110,116,32,83,111,102,116,119,97,114,101,32,105,115,32,102,117,114,110,105,115,104,101,100, +32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116, +32,97,110,100,32,116,114,97,100,101,109,97,114,107,32,110,111,116,105,99,101,115,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32, +105,110,32,97,108,108,32,99,111,112,105,101,115,32,111,102,32,111,110,101,32,111,114,32,109,111,114,101,32,111,102,32,116,104,101,32,70,111,110,116,32,83,111,102,116,119,97,114,101,32,116,121,112,101,102,97,99,101,115,46,10,10,84,104,101,32,70,111,110, +116,32,83,111,102,116,119,97,114,101,32,109,97,121,32,98,101,32,109,111,100,105,102,105,101,100,44,32,97,108,116,101,114,101,100,44,32,111,114,32,97,100,100,101,100,32,116,111,44,32,97,110,100,32,105,110,32,112,97,114,116,105,99,117,108,97,114,32,116, +104,101,32,100,101,115,105,103,110,115,32,111,102,32,103,108,121,112,104,115,32,111,114,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,116,104,101,32,70,111,110,116,115,32,109,97,121,32,98,101,32,109,111,100,105,102,105,101,100,32,97,110,100,32, +97,100,100,105,116,105,111,110,97,108,32,103,108,121,112,104,115,32,111,114,32,32,111,114,32,99,104,97,114,97,99,116,101,114,115,32,109,97,121,32,98,101,32,97,100,100,101,100,32,116,111,32,116,104,101,32,70,111,110,116,115,44,32,111,110,108,121,32,105, +102,32,116,104,101,32,102,111,110,116,115,32,97,114,101,32,114,101,110,97,109,101,100,32,116,111,32,110,97,109,101,115,32,110,111,116,32,99,111,110,116,97,105,110,105,110,103,32,101,105,116,104,101,114,32,116,104,101,32,119,111,114,100,115,32,34,66,105, +116,115,116,114,101,97,109,34,32,111,114,32,116,104,101,32,119,111,114,100,32,34,86,101,114,97,34,46,10,10,84,104,105,115,32,76,105,99,101,110,115,101,32,98,101,99,111,109,101,115,32,110,117,108,108,32,97,110,100,32,118,111,105,100,32,116,111,32,116, +104,101,32,101,120,116,101,110,116,32,97,112,112,108,105,99,97,98,108,101,32,116,111,32,70,111,110,116,115,32,111,114,32,70,111,110,116,32,83,111,102,116,119,97,114,101,32,116,104,97,116,32,104,97,115,32,98,101,101,110,32,109,111,100,105,102,105,101, +100,32,97,110,100,32,105,115,32,100,105,115,116,114,105,98,117,116,101,100,32,117,110,100,101,114,32,116,104,101,32,34,66,105,116,115,116,114,101,97,109,32,86,101,114,97,34,32,110,97,109,101,115,46,10,10,84,104,101,32,70,111,110,116,32,83,111,102,116, +119,97,114,101,32,109,97,121,32,98,101,32,115,111,108,100,32,97,115,32,112,97,114,116,32,111,102,32,97,32,108,97,114,103,101,114,32,115,111,102,116,119,97,114,101,32,112,97,99,107,97,103,101,32,98,117,116,32,110,111,32,99,111,112,121,32,111,102,32,111, +110,101,32,111,114,32,109,111,114,101,32,111,102,32,116,104,101,32,70,111,110,116,32,83,111,102,116,119,97,114,101,32,116,121,112,101,102,97,99,101,115,32,109,97,121,32,98,101,32,115,111,108,100,32,98,121,32,105,116,115,101,108,102,46,10,10,84,72,69, +32,70,79,78,84,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,32,73,77,80,76,73,69,68, +44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,65,78,89,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,32,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84, +73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,32,79,70,32,67,79,80,89,82,73,71,72,84,44,32,80,65,84,69,78,84,44,32,84,82,65,68,69,77,65,82,75,44,32,79,82,32,79,84,72,69,82,32,82,73,71,72,84,46,32, +73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,66,73,84,83,84,82,69,65,77,32,79,82,32,84,72,69,32,71,78,79,77,69,32,70,79,85,78,68,65,84,73,79,78,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83, +32,79,82,32,79,84,72,69,82,32,76,73,65,66,73,76,73,84,89,44,32,73,78,67,76,85,68,73,78,71,32,65,78,89,32,71,69,78,69,82,65,76,44,32,83,80,69,67,73,65,76,44,32,73,78,68,73,82,69,67,84,44,32,73,78,67,73,68,69,78,84,65,76,44,32,79,82,32,67,79,78,83,69,81, +85,69,78,84,73,65,76,32,68,65,77,65,71,69,83,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,32, +79,85,84,32,79,70,32,84,72,69,32,85,83,69,32,79,82,32,73,78,65,66,73,76,73,84,89,32,84,79,32,85,83,69,32,84,72,69,32,70,79,78,84,32,83,79,70,84,87,65,82,69,32,79,82,32,70,82,79,77,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,32,70, +79,78,84,32,83,79,70,84,87,65,82,69,46,10,10,69,120,99,101,112,116,32,97,115,32,99,111,110,116,97,105,110,101,100,32,105,110,32,116,104,105,115,32,110,111,116,105,99,101,44,32,116,104,101,32,110,97,109,101,115,32,111,102,32,71,110,111,109,101,44,32,116, +104,101,32,71,110,111,109,101,32,70,111,117,110,100,97,116,105,111,110,44,32,97,110,100,32,66,105,116,115,116,114,101,97,109,32,73,110,99,46,44,32,115,104,97,108,108,32,110,111,116,32,98,101,32,117,115,101,100,32,105,110,32,97,100,118,101,114,116,105, +115,105,110,103,32,111,114,32,111,116,104,101,114,119,105,115,101,32,116,111,32,112,114,111,109,111,116,101,32,116,104,101,32,115,97,108,101,44,32,117,115,101,32,111,114,32,111,116,104,101,114,32,100,101,97,108,105,110,103,115,32,105,110,32,116,104,105, +115,32,70,111,110,116,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,119,114,105,116,116,101,110,32,97,117,116,104,111,114,105,122,97,116,105,111,110,32,102,114,111,109,32,116,104,101,32,71,110,111,109,101,32, +70,111,117,110,100,97,116,105,111,110,32,111,114,32,66,105,116,115,116,114,101,97,109,32,73,110,99,46,44,32,114,101,115,112,101,99,116,105,118,101,108,121,46,32,70,111,114,32,102,117,114,116,104,101,114,32,105,110,102,111,114,109,97,116,105,111,110,44, +32,99,111,110,116,97,99,116,58,32,102,111,110,116,115,32,97,116,32,103,110,111,109,101,32,100,111,116,32,111,114,103,46,32,10,0,0,104,0,116,0,116,0,112,0,58,0,47,0,47,0,100,0,101,0,106,0,97,0,118,0,117,0,46,0,115,0,111,0,117,0,114,0,99,0,101,0,102,0, +111,0,114,0,103,0,101,0,46,0,110,0,101,0,116,0,47,0,119,0,105,0,107,0,105,0,47,0,105,0,110,0,100,0,101,0,120,0,46,0,112,0,104,0,112,0,47,0,76,0,105,0,99,0,101,0,110,0,115,0,101,0,0,104,116,116,112,58,47,47,100,101,106,97,118,117,46,115,111,117,114,99, +101,102,111,114,103,101,46,110,101,116,47,119,105,107,105,47,105,110,100,101,120,46,112,104,112,47,76,105,99,101,110,115,101,0,0,0,0,0,2,0,0,0,0,0,0,255,126,0,90,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,49,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0, +10,0,11,0,12,0,13,0,14,0,15,0,16,0,17,0,18,0,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0,30,0,31,0,32,0,33,0,34,0,35,0,36,0,37,0,38,0,39,0,40,0,41,0,42,0,43,0,44,0,45,0,46,0,47,0,48,0,49,0,50,0,51,0,52,0,53,0,54,0,55,0,56,0,57,0,58,0,59,0, +60,0,61,0,62,0,63,0,64,0,65,0,66,0,67,0,68,0,69,0,70,0,71,0,72,0,73,0,74,0,75,0,76,0,77,0,78,0,79,0,80,0,81,0,82,0,83,0,84,0,85,0,86,0,87,0,88,0,89,0,90,0,91,0,92,0,93,0,94,0,95,0,96,0,97,0,172,0,163,0,132,0,133,0,189,0,150,0,232,0,134,0,142,0,139,0, +157,0,169,0,164,1,2,0,138,0,218,0,131,0,147,0,242,0,243,0,141,0,151,0,136,0,195,0,222,0,241,0,158,0,170,0,245,0,244,0,246,0,162,0,173,0,201,0,199,0,174,0,98,0,99,0,144,0,100,0,203,0,101,0,200,0,202,0,207,0,204,0,205,0,206,0,233,0,102,0,211,0,208,0,209, +0,175,0,103,0,240,0,145,0,214,0,212,0,213,0,104,0,235,0,237,0,137,0,106,0,105,0,107,0,109,0,108,0,110,0,160,0,111,0,113,0,112,0,114,0,115,0,117,0,116,0,118,0,119,0,234,0,120,0,122,0,121,0,123,0,125,0,124,0,184,0,161,0,127,0,126,0,128,0,129,0,236,0,238, +0,186,1,3,1,4,1,5,1,6,1,7,1,8,0,253,0,254,1,9,1,10,1,11,1,12,0,255,1,0,1,13,1,14,1,15,1,1,1,16,1,17,1,18,1,19,1,20,1,21,1,22,1,23,1,24,1,25,1,26,1,27,0,248,0,249,1,28,1,29,1,30,1,31,1,32,1,33,1,34,1,35,1,36,1,37,1,38,1,39,1,40,1,41,1,42,1,43,0,250,0, +215,1,44,1,45,1,46,1,47,1,48,1,49,1,50,1,51,1,52,1,53,1,54,1,55,1,56,1,57,1,58,0,226,0,227,1,59,1,60,1,61,1,62,1,63,1,64,1,65,1,66,1,67,1,68,1,69,1,70,1,71,1,72,1,73,0,176,0,177,1,74,1,75,1,76,1,77,1,78,1,79,1,80,1,81,1,82,1,83,0,251,0,252,0,228,0,229, +1,84,1,85,1,86,1,87,1,88,1,89,1,90,1,91,1,92,1,93,1,94,1,95,1,96,1,97,1,98,1,99,1,100,1,101,1,102,1,103,1,104,1,105,0,187,1,106,1,107,1,108,1,109,0,230,0,231,1,110,1,111,1,112,1,113,1,114,1,115,1,116,1,117,1,118,1,119,1,120,1,121,1,122,1,123,1,124,1, +125,1,126,1,127,1,128,0,166,1,129,1,130,1,131,1,132,1,133,1,134,1,135,1,136,1,137,1,138,1,139,1,140,1,141,1,142,1,143,1,144,1,145,1,146,1,147,1,148,1,149,1,150,1,151,1,152,1,153,1,154,1,155,1,156,1,157,1,158,1,159,1,160,1,161,1,162,1,163,1,164,1,165, +1,166,1,167,1,168,1,169,1,170,1,171,1,172,1,173,1,174,1,175,1,176,1,177,1,178,1,179,1,180,1,181,1,182,1,183,1,184,1,185,1,186,1,187,1,188,1,189,1,190,1,191,1,192,1,193,1,194,1,195,1,196,1,197,1,198,1,199,1,200,1,201,1,202,1,203,1,204,1,205,1,206,1,207, +1,208,1,209,1,210,1,211,1,212,1,213,1,214,1,215,1,216,1,217,1,218,1,219,1,220,1,221,1,222,1,223,1,224,1,225,1,226,1,227,1,228,1,229,1,230,1,231,1,232,1,233,1,234,1,235,1,236,1,237,1,238,1,239,1,240,1,241,1,242,1,243,1,244,1,245,1,246,1,247,1,248,1,249, +1,250,1,251,1,252,1,253,1,254,1,255,2,0,2,1,2,2,2,3,2,4,2,5,2,6,2,7,2,8,2,9,2,10,2,11,2,12,2,13,2,14,2,15,2,16,2,17,2,18,2,19,2,20,2,21,2,22,2,23,2,24,2,25,2,26,2,27,2,28,2,29,2,30,2,31,2,32,2,33,2,34,2,35,2,36,2,37,2,38,2,39,2,40,2,41,2,42,2,43,2,44, +2,45,2,46,2,47,2,48,2,49,2,50,2,51,2,52,2,53,2,54,2,55,2,56,2,57,2,58,2,59,2,60,2,61,2,62,2,63,2,64,2,65,2,66,2,67,2,68,2,69,2,70,2,71,2,72,2,73,2,74,2,75,2,76,2,77,2,78,2,79,2,80,2,81,2,82,2,83,2,84,2,85,2,86,2,87,2,88,2,89,2,90,2,91,2,92,2,93,2,94, +2,95,2,96,2,97,2,98,2,99,2,100,2,101,2,102,2,103,2,104,2,105,2,106,2,107,2,108,2,109,2,110,2,111,2,112,2,113,2,114,2,115,2,116,2,117,2,118,2,119,2,120,2,121,2,122,2,123,2,124,2,125,2,126,2,127,2,128,2,129,2,130,2,131,2,132,2,133,2,134,2,135,2,136,2,137, +2,138,2,139,2,140,2,141,2,142,2,143,2,144,2,145,2,146,0,216,0,225,2,147,2,148,2,149,2,150,2,151,2,152,2,153,2,154,2,155,2,156,2,157,2,158,0,219,0,220,0,221,0,224,0,217,0,223,2,159,2,160,2,161,2,162,2,163,2,164,2,165,2,166,2,167,2,168,2,169,2,170,2,171, +2,172,2,173,2,174,2,175,2,176,2,177,2,178,2,179,2,180,2,181,2,182,2,183,2,184,2,185,2,186,2,187,2,188,2,189,2,190,2,191,2,192,2,193,2,194,2,195,2,196,2,197,2,198,2,199,2,200,2,201,2,202,2,203,2,204,2,205,2,206,2,207,2,208,2,209,2,210,2,211,2,212,2,213, +2,214,2,215,2,216,2,217,2,218,2,219,2,220,2,221,2,222,2,223,2,224,2,225,2,226,2,227,2,228,2,229,2,230,2,231,2,232,2,233,2,234,2,235,2,236,2,237,2,238,2,239,2,240,2,241,2,242,2,243,2,244,2,245,2,246,2,247,2,248,2,249,2,250,2,251,2,252,2,253,2,254,2,255, +3,0,3,1,3,2,3,3,3,4,3,5,3,6,3,7,3,8,3,9,3,10,3,11,3,12,3,13,3,14,3,15,3,16,3,17,3,18,3,19,3,20,3,21,3,22,3,23,3,24,3,25,3,26,0,159,3,27,3,28,3,29,3,30,3,31,3,32,3,33,3,34,3,35,3,36,3,37,3,38,3,39,3,40,3,41,3,42,3,43,3,44,3,45,3,46,3,47,3,48,0,155,3,49, +3,50,3,51,3,52,3,53,3,54,3,55,3,56,3,57,3,58,3,59,3,60,3,61,3,62,3,63,3,64,3,65,3,66,3,67,3,68,3,69,3,70,3,71,3,72,3,73,3,74,3,75,3,76,3,77,3,78,3,79,3,80,3,81,3,82,3,83,3,84,3,85,3,86,3,87,3,88,3,89,3,90,3,91,3,92,3,93,3,94,3,95,3,96,3,97,3,98,3,99, +3,100,3,101,3,102,3,103,3,104,3,105,3,106,3,107,3,108,3,109,3,110,3,111,3,112,3,113,3,114,3,115,3,116,3,117,3,118,3,119,3,120,3,121,3,122,3,123,3,124,3,125,3,126,3,127,3,128,3,129,3,130,3,131,3,132,3,133,3,134,3,135,3,136,3,137,3,138,3,139,3,140,3,141, +3,142,3,143,3,144,3,145,3,146,3,147,3,148,3,149,3,150,3,151,3,152,3,153,3,154,3,155,3,156,3,157,3,158,3,159,3,160,3,161,3,162,3,163,3,164,3,165,3,166,3,167,3,168,3,169,3,170,3,171,3,172,3,173,3,174,3,175,3,176,3,177,3,178,3,179,3,180,3,181,3,182,3,183, +3,184,3,185,3,186,3,187,3,188,3,189,3,190,3,191,3,192,3,193,3,194,3,195,3,196,3,197,3,198,3,199,3,200,3,201,3,202,3,203,3,204,3,205,3,206,3,207,3,208,3,209,3,210,3,211,3,212,3,213,3,214,3,215,3,216,3,217,3,218,3,219,3,220,3,221,3,222,3,223,3,224,3,225, +3,226,3,227,3,228,3,229,3,230,3,231,3,232,3,233,3,234,3,235,3,236,3,237,3,238,3,239,3,240,3,241,3,242,3,243,3,244,3,245,3,246,3,247,3,248,3,249,3,250,3,251,3,252,3,253,3,254,3,255,4,0,4,1,4,2,4,3,4,4,4,5,4,6,4,7,4,8,4,9,4,10,4,11,4,12,4,13,4,14,4,15, +4,16,4,17,4,18,4,19,4,20,4,21,4,22,4,23,4,24,4,25,4,26,4,27,4,28,4,29,4,30,4,31,4,32,4,33,4,34,4,35,4,36,4,37,4,38,4,39,4,40,4,41,4,42,4,43,4,44,4,45,4,46,4,47,4,48,4,49,4,50,4,51,4,52,4,53,4,54,4,55,4,56,4,57,4,58,4,59,4,60,4,61,4,62,4,63,4,64,4,65, +4,66,4,67,4,68,4,69,4,70,4,71,4,72,4,73,4,74,4,75,4,76,4,77,4,78,4,79,4,80,4,81,4,82,4,83,4,84,4,85,4,86,4,87,4,88,4,89,4,90,4,91,4,92,4,93,4,94,4,95,4,96,4,97,4,98,4,99,4,100,4,101,4,102,4,103,4,104,4,105,4,106,4,107,4,108,4,109,4,110,4,111,4,112,4, +113,4,114,4,115,4,116,4,117,4,118,4,119,4,120,4,121,4,122,4,123,4,124,4,125,4,126,4,127,4,128,4,129,4,130,4,131,4,132,4,133,4,134,4,135,4,136,4,137,4,138,4,139,4,140,4,141,4,142,4,143,4,144,4,145,4,146,4,147,4,148,4,149,4,150,4,151,4,152,4,153,4,154, +4,155,4,156,4,157,4,158,4,159,4,160,4,161,4,162,4,163,4,164,4,165,4,166,4,167,4,168,4,169,4,170,4,171,4,172,4,173,4,174,4,175,4,176,4,177,4,178,4,179,4,180,4,181,4,182,4,183,4,184,4,185,4,186,4,187,4,188,4,189,4,190,4,191,4,192,4,193,4,194,4,195,4,196, +4,197,4,198,4,199,4,200,4,201,4,202,4,203,4,204,4,205,4,206,4,207,4,208,4,209,4,210,4,211,4,212,4,213,4,214,4,215,4,216,4,217,4,218,4,219,4,220,4,221,4,222,4,223,4,224,4,225,4,226,4,227,4,228,4,229,4,230,4,231,4,232,4,233,4,234,4,235,4,236,4,237,4,238, +4,239,4,240,4,241,4,242,4,243,4,244,4,245,4,246,4,247,4,248,4,249,4,250,4,251,4,252,4,253,4,254,4,255,5,0,5,1,5,2,5,3,5,4,5,5,5,6,5,7,5,8,5,9,5,10,5,11,5,12,5,13,5,14,5,15,5,16,5,17,5,18,5,19,5,20,5,21,5,22,5,23,5,24,5,25,5,26,5,27,5,28,5,29,5,30,5,31, +5,32,5,33,5,34,5,35,5,36,5,37,5,38,5,39,5,40,5,41,5,42,5,43,5,44,5,45,5,46,5,47,5,48,5,49,5,50,5,51,5,52,5,53,5,54,5,55,5,56,5,57,5,58,5,59,5,60,5,61,5,62,5,63,5,64,5,65,5,66,5,67,5,68,5,69,5,70,5,71,5,72,5,73,5,74,5,75,5,76,5,77,5,78,5,79,5,80,5,81, +5,82,5,83,5,84,5,85,5,86,5,87,5,88,5,89,5,90,5,91,5,92,5,93,5,94,5,95,5,96,5,97,5,98,5,99,5,100,5,101,5,102,5,103,5,104,5,105,5,106,5,107,5,108,5,109,5,110,5,111,5,112,5,113,5,114,5,115,5,116,5,117,5,118,5,119,5,120,5,121,5,122,5,123,5,124,5,125,5,126, +5,127,5,128,5,129,5,130,5,131,5,132,5,133,5,134,5,135,5,136,5,137,5,138,5,139,5,140,5,141,5,142,5,143,5,144,5,145,5,146,5,147,5,148,5,149,5,150,5,151,5,152,5,153,5,154,5,155,5,156,5,157,5,158,5,159,5,160,5,161,5,162,5,163,5,164,5,165,5,166,5,167,5,168, +5,169,5,170,5,171,5,172,5,173,5,174,5,175,5,176,5,177,5,178,5,179,5,180,5,181,5,182,5,183,5,184,5,185,5,186,5,187,5,188,5,189,5,190,5,191,5,192,5,193,5,194,5,195,5,196,5,197,5,198,5,199,5,200,5,201,5,202,5,203,5,204,5,205,5,206,5,207,5,208,5,209,5,210, +5,211,5,212,5,213,5,214,5,215,5,216,5,217,5,218,5,219,5,220,5,221,5,222,5,223,5,224,5,225,5,226,5,227,5,228,5,229,5,230,5,231,5,232,5,233,5,234,5,235,5,236,5,237,5,238,5,239,5,240,5,241,5,242,5,243,5,244,5,245,5,246,5,247,5,248,5,249,5,250,5,251,5,252, +5,253,5,254,5,255,6,0,6,1,6,2,6,3,6,4,6,5,6,6,6,7,6,8,6,9,6,10,6,11,6,12,6,13,6,14,6,15,6,16,6,17,6,18,6,19,6,20,6,21,6,22,6,23,6,24,6,25,6,26,6,27,6,28,6,29,6,30,6,31,6,32,6,33,6,34,6,35,6,36,6,37,6,38,6,39,6,40,6,41,6,42,6,43,6,44,6,45,6,46,6,47,6, +48,6,49,6,50,6,51,6,52,6,53,6,54,6,55,6,56,6,57,6,58,6,59,6,60,6,61,6,62,6,63,6,64,6,65,6,66,6,67,6,68,6,69,6,70,6,71,6,72,6,73,6,74,6,75,6,76,6,77,6,78,6,79,6,80,6,81,6,82,6,83,6,84,6,85,6,86,6,87,6,88,6,89,6,90,6,91,6,92,6,93,6,94,6,95,6,96,6,97,6, +98,6,99,6,100,6,101,6,102,6,103,6,104,6,105,6,106,6,107,6,108,6,109,6,110,6,111,6,112,6,113,6,114,6,115,6,116,6,117,6,118,6,119,6,120,6,121,6,122,6,123,6,124,6,125,6,126,6,127,6,128,6,129,6,130,6,131,6,132,6,133,6,134,6,135,6,136,6,137,6,138,6,139,6, +140,6,141,6,142,6,143,6,144,6,145,6,146,6,147,6,148,6,149,6,150,6,151,6,152,6,153,6,154,6,155,6,156,6,157,6,158,6,159,6,160,6,161,6,162,6,163,6,164,6,165,6,166,6,167,6,168,6,169,6,170,6,171,6,172,6,173,6,174,6,175,6,176,6,177,6,178,6,179,6,180,6,181, +6,182,6,183,6,184,6,185,6,186,6,187,6,188,6,189,6,190,6,191,6,192,6,193,6,194,6,195,6,196,6,197,6,198,6,199,6,200,6,201,6,202,6,203,6,204,6,205,6,206,6,207,6,208,6,209,6,210,6,211,6,212,6,213,6,214,6,215,6,216,6,217,6,218,6,219,6,220,6,221,6,222,6,223, +6,224,6,225,6,226,6,227,6,228,6,229,6,230,6,231,6,232,6,233,6,234,6,235,6,236,6,237,6,238,6,239,6,240,6,241,6,242,6,243,6,244,6,245,6,246,6,247,6,248,6,249,6,250,6,251,6,252,6,253,6,254,6,255,7,0,7,1,7,2,7,3,7,4,7,5,7,6,7,7,7,8,7,9,7,10,7,11,7,12,7,13, +7,14,7,15,7,16,7,17,7,18,7,19,7,20,7,21,7,22,7,23,7,24,7,25,7,26,7,27,7,28,7,29,7,30,7,31,7,32,7,33,7,34,7,35,7,36,7,37,7,38,7,39,7,40,7,41,7,42,7,43,7,44,7,45,7,46,7,47,7,48,7,49,7,50,7,51,7,52,7,53,7,54,7,55,7,56,7,57,7,58,7,59,7,60,7,61,7,62,7,63, +0,178,0,179,7,64,7,65,7,66,0,182,0,183,0,196,7,67,0,180,0,181,0,197,7,68,0,130,0,194,0,135,7,69,0,171,7,70,0,198,7,71,7,72,7,73,7,74,7,75,7,76,7,77,0,190,0,191,7,78,7,79,7,80,7,81,7,82,7,83,7,84,7,85,7,86,7,87,7,88,7,89,7,90,7,91,7,92,7,93,7,94,7,95, +7,96,7,97,7,98,7,99,7,100,7,101,7,102,7,103,7,104,7,105,7,106,7,107,7,108,7,109,7,110,7,111,7,112,7,113,7,114,7,115,7,116,7,117,7,118,7,119,7,120,7,121,7,122,7,123,7,124,7,125,7,126,7,127,7,128,7,129,7,130,7,131,7,132,7,133,0,247,7,134,7,135,7,136,7, +137,7,138,7,139,7,140,7,141,7,142,7,143,7,144,7,145,7,146,7,147,7,148,7,149,7,150,7,151,7,152,7,153,7,154,7,155,7,156,7,157,7,158,7,159,7,160,7,161,7,162,7,163,7,164,7,165,7,166,0,140,7,167,7,168,7,169,7,170,7,171,7,172,7,173,7,174,7,175,7,176,7,177, +7,178,7,179,7,180,7,181,7,182,7,183,7,184,7,185,7,186,7,187,7,188,7,189,7,190,7,191,7,192,7,193,7,194,7,195,7,196,7,197,7,198,7,199,7,200,7,201,7,202,7,203,7,204,7,205,7,206,7,207,7,208,7,209,7,210,7,211,7,212,7,213,7,214,7,215,7,216,7,217,7,218,7,219, +7,220,7,221,7,222,7,223,7,224,7,225,7,226,7,227,7,228,7,229,7,230,7,231,7,232,7,233,7,234,7,235,7,236,7,237,7,238,7,239,7,240,7,241,7,242,7,243,7,244,7,245,7,246,7,247,7,248,7,249,7,250,7,251,7,252,7,253,7,254,7,255,8,0,8,1,8,2,8,3,8,4,8,5,8,6,8,7,8, +8,8,9,8,10,8,11,8,12,8,13,8,14,8,15,8,16,8,17,8,18,8,19,8,20,8,21,8,22,8,23,8,24,8,25,8,26,8,27,8,28,8,29,8,30,8,31,8,32,8,33,8,34,8,35,8,36,8,37,8,38,8,39,8,40,8,41,8,42,8,43,8,44,8,45,8,46,0,152,8,47,8,48,8,49,0,168,8,50,8,51,8,52,8,53,8,54,8,55,8, +56,8,57,0,154,8,58,0,153,0,239,8,59,8,60,8,61,8,62,8,63,0,165,8,64,8,65,8,66,0,146,8,67,8,68,8,69,8,70,8,71,8,72,8,73,0,156,8,74,8,75,8,76,8,77,8,78,8,79,8,80,8,81,8,82,8,83,8,84,8,85,8,86,8,87,8,88,8,89,8,90,8,91,8,92,0,167,8,93,8,94,8,95,8,96,8,97, +8,98,8,99,8,100,8,101,8,102,8,103,8,104,8,105,8,106,8,107,8,108,8,109,8,110,8,111,8,112,8,113,8,114,8,115,0,143,8,116,8,117,8,118,0,148,0,149,8,119,8,120,8,121,8,122,8,123,8,124,8,125,8,126,8,127,8,128,8,129,8,130,8,131,8,132,8,133,8,134,8,135,8,136, +8,137,8,138,8,139,8,140,8,141,8,142,8,143,8,144,8,145,8,146,8,147,8,148,8,149,8,150,8,151,8,152,8,153,8,154,8,155,8,156,8,157,8,158,8,159,8,160,8,161,8,162,8,163,8,164,8,165,8,166,8,167,8,168,8,169,8,170,8,171,8,172,8,173,8,174,8,175,8,176,8,177,8,178, +8,179,8,180,8,181,8,182,8,183,8,184,8,185,8,186,8,187,8,188,8,189,8,190,8,191,8,192,8,193,8,194,8,195,8,196,8,197,8,198,8,199,8,200,8,201,8,202,8,203,8,204,8,205,8,206,8,207,8,208,8,209,8,210,8,211,8,212,8,213,8,214,8,215,8,216,8,217,8,218,8,219,8,220, +8,221,8,222,8,223,8,224,8,225,8,226,8,227,8,228,8,229,8,230,8,231,8,232,8,233,8,234,8,235,8,236,8,237,8,238,8,239,8,240,8,241,8,242,8,243,8,244,8,245,8,246,8,247,8,248,8,249,8,250,8,251,8,252,8,253,8,254,8,255,9,0,9,1,9,2,9,3,9,4,9,5,9,6,9,7,9,8,9,9, +9,10,9,11,9,12,9,13,9,14,9,15,9,16,9,17,9,18,9,19,9,20,9,21,9,22,9,23,9,24,9,25,9,26,9,27,9,28,9,29,9,30,9,31,9,32,9,33,9,34,9,35,9,36,9,37,9,38,9,39,9,40,9,41,9,42,9,43,9,44,9,45,9,46,9,47,9,48,9,49,9,50,9,51,9,52,9,53,9,54,9,55,9,56,9,57,9,58,9,59, +9,60,9,61,9,62,9,63,9,64,9,65,9,66,9,67,9,68,9,69,9,70,9,71,9,72,9,73,9,74,9,75,9,76,9,77,9,78,9,79,9,80,9,81,9,82,9,83,9,84,9,85,9,86,9,87,9,88,9,89,9,90,9,91,9,92,9,93,9,94,9,95,9,96,9,97,9,98,9,99,9,100,9,101,9,102,9,103,9,104,9,105,9,106,9,107,9, +108,9,109,9,110,9,111,9,112,9,113,9,114,9,115,9,116,9,117,9,118,9,119,9,120,9,121,9,122,9,123,9,124,9,125,9,126,9,127,9,128,9,129,9,130,9,131,9,132,9,133,9,134,9,135,9,136,9,137,9,138,9,139,9,140,9,141,9,142,9,143,9,144,9,145,9,146,9,147,9,148,9,149, +9,150,9,151,9,152,9,153,9,154,9,155,9,156,9,157,9,158,9,159,9,160,9,161,9,162,9,163,9,164,9,165,9,166,9,167,9,168,9,169,9,170,9,171,9,172,9,173,9,174,9,175,9,176,9,177,9,178,9,179,9,180,9,181,9,182,9,183,9,184,9,185,9,186,9,187,9,188,9,189,9,190,9,191, +9,192,9,193,9,194,9,195,9,196,9,197,9,198,9,199,9,200,9,201,9,202,9,203,9,204,9,205,9,206,9,207,9,208,9,209,9,210,9,211,9,212,9,213,9,214,9,215,9,216,9,217,9,218,9,219,9,220,9,221,9,222,9,223,9,224,9,225,9,226,9,227,9,228,9,229,9,230,9,231,9,232,9,233, +9,234,9,235,9,236,9,237,9,238,9,239,9,240,9,241,9,242,9,243,9,244,9,245,9,246,9,247,9,248,9,249,9,250,9,251,9,252,9,253,9,254,9,255,10,0,10,1,10,2,10,3,10,4,10,5,10,6,10,7,10,8,10,9,10,10,10,11,10,12,10,13,10,14,10,15,10,16,10,17,10,18,10,19,10,20,10, +21,10,22,10,23,10,24,10,25,10,26,10,27,10,28,10,29,10,30,10,31,10,32,10,33,10,34,10,35,10,36,10,37,0,185,10,38,10,39,10,40,10,41,10,42,10,43,10,44,10,45,10,46,10,47,10,48,10,49,10,50,10,51,10,52,10,53,10,54,10,55,10,56,10,57,10,58,10,59,10,60,10,61,10, +62,10,63,10,64,10,65,10,66,10,67,10,68,10,69,10,70,10,71,10,72,10,73,10,74,10,75,10,76,10,77,10,78,10,79,10,80,10,81,10,82,10,83,10,84,10,85,10,86,10,87,10,88,10,89,10,90,10,91,10,92,10,93,10,94,10,95,10,96,10,97,10,98,10,99,10,100,10,101,10,102,10,103, +10,104,10,105,10,106,10,107,10,108,10,109,10,110,10,111,10,112,10,113,10,114,10,115,10,116,10,117,10,118,10,119,10,120,10,121,10,122,10,123,10,124,10,125,10,126,10,127,10,128,10,129,10,130,10,131,10,132,10,133,10,134,10,135,10,136,10,137,10,138,10,139, +10,140,10,141,10,142,10,143,10,144,10,145,10,146,10,147,10,148,10,149,10,150,10,151,10,152,10,153,10,154,10,155,10,156,10,157,10,158,10,159,10,160,10,161,10,162,10,163,10,164,10,165,10,166,10,167,10,168,10,169,10,170,10,171,10,172,10,173,10,174,10,175, +10,176,10,177,10,178,10,179,10,180,10,181,10,182,10,183,10,184,10,185,10,186,10,187,10,188,10,189,10,190,10,191,10,192,10,193,10,194,10,195,10,196,10,197,10,198,10,199,10,200,10,201,10,202,10,203,10,204,10,205,10,206,10,207,10,208,10,209,10,210,10,211, +10,212,10,213,10,214,10,215,10,216,10,217,10,218,10,219,10,220,10,221,10,222,10,223,10,224,10,225,10,226,10,227,10,228,10,229,10,230,10,231,10,232,10,233,10,234,10,235,10,236,10,237,10,238,10,239,10,240,10,241,10,242,10,243,10,244,10,245,10,246,10,247, +10,248,10,249,10,250,10,251,10,252,10,253,10,254,10,255,11,0,11,1,11,2,11,3,11,4,11,5,11,6,11,7,11,8,11,9,11,10,11,11,11,12,11,13,11,14,11,15,11,16,11,17,11,18,11,19,11,20,11,21,11,22,11,23,11,24,11,25,11,26,11,27,11,28,11,29,11,30,11,31,11,32,11,33, +11,34,11,35,11,36,11,37,11,38,11,39,11,40,11,41,11,42,11,43,11,44,11,45,11,46,11,47,11,48,11,49,11,50,11,51,11,52,11,53,11,54,11,55,11,56,11,57,11,58,11,59,11,60,11,61,11,62,11,63,11,64,11,65,11,66,11,67,11,68,11,69,11,70,11,71,11,72,11,73,11,74,11,75, +11,76,11,77,11,78,11,79,11,80,11,81,11,82,11,83,11,84,11,85,11,86,11,87,11,88,11,89,11,90,11,91,11,92,11,93,11,94,11,95,11,96,11,97,11,98,11,99,11,100,11,101,11,102,11,103,11,104,11,105,11,106,11,107,11,108,11,109,11,110,11,111,11,112,11,113,11,114,11, +115,11,116,11,117,11,118,11,119,11,120,11,121,11,122,11,123,11,124,11,125,11,126,11,127,11,128,11,129,11,130,11,131,11,132,11,133,11,134,11,135,11,136,11,137,11,138,11,139,11,140,11,141,11,142,11,143,11,144,11,145,11,146,11,147,11,148,11,149,11,150,11, +151,11,152,11,153,11,154,11,155,11,156,11,157,11,158,11,159,11,160,11,161,11,162,11,163,11,164,11,165,11,166,11,167,11,168,11,169,11,170,11,171,11,172,11,173,11,174,11,175,11,176,11,177,11,178,11,179,11,180,11,181,11,182,11,183,11,184,11,185,11,186,11, +187,11,188,11,189,11,190,11,191,11,192,11,193,11,194,11,195,11,196,11,197,11,198,11,199,11,200,11,201,11,202,11,203,11,204,11,205,11,206,11,207,11,208,11,209,11,210,11,211,11,212,11,213,11,214,11,215,11,216,11,217,11,218,11,219,11,220,11,221,11,222,11, +223,11,224,11,225,11,226,11,227,11,228,11,229,0,192,0,193,11,230,11,231,11,232,11,233,11,234,11,235,11,236,11,237,11,238,11,239,11,240,11,241,11,242,11,243,11,244,11,245,11,246,11,247,11,248,11,249,11,250,11,251,11,252,11,253,11,254,11,255,12,0,12,1, +12,2,12,3,12,4,12,5,12,6,12,7,12,8,12,9,12,10,12,11,12,12,12,13,12,14,12,15,12,16,12,17,12,18,12,19,12,20,12,21,12,22,12,23,12,24,12,25,12,26,12,27,12,28,12,29,12,30,12,31,12,32,12,33,12,34,12,35,12,36,12,37,12,38,12,39,12,40,12,41,12,42,12,43,12,44, +12,45,12,46,12,47,12,48,12,49,12,50,12,51,12,52,12,53,12,54,12,55,12,56,12,57,12,58,12,59,12,60,12,61,12,62,12,63,12,64,12,65,12,66,12,67,12,68,12,69,12,70,12,71,12,72,12,73,12,74,12,75,12,76,12,77,12,78,12,79,12,80,12,81,12,82,12,83,12,84,12,85,12,86, +12,87,12,88,12,89,12,90,12,91,12,92,12,93,12,94,12,95,12,96,12,97,12,98,12,99,12,100,12,101,12,102,12,103,12,104,12,105,12,106,12,107,12,108,12,109,12,110,12,111,12,112,12,113,12,114,12,115,12,116,12,117,12,118,12,119,12,120,12,121,12,122,12,123,12,124, +12,125,12,126,12,127,12,128,12,129,12,130,12,131,12,132,12,133,12,134,12,135,12,136,12,137,12,138,12,139,12,140,12,141,12,142,12,143,12,144,12,145,12,146,12,147,12,148,12,149,12,150,12,151,12,152,12,153,12,154,12,155,12,156,12,157,12,158,12,159,12,160, +12,161,12,162,12,163,12,164,12,165,12,166,12,167,12,168,12,169,12,170,12,171,12,172,12,173,12,174,12,175,12,176,12,177,12,178,12,179,12,180,12,181,12,182,12,183,12,184,12,185,12,186,12,187,12,188,12,189,12,190,12,191,12,192,12,193,12,194,12,195,12,196, +12,197,12,198,12,199,12,200,12,201,12,202,12,203,12,204,12,205,12,206,12,207,12,208,12,209,12,210,12,211,12,212,12,213,12,214,12,215,12,216,12,217,12,218,12,219,12,220,12,221,12,222,12,223,12,224,12,225,12,226,12,227,12,228,12,229,12,230,12,231,12,232, +12,233,12,234,12,235,12,236,12,237,12,238,12,239,12,240,12,241,12,242,12,243,12,244,12,245,12,246,12,247,12,248,12,249,12,250,12,251,12,252,12,253,12,254,12,255,13,0,13,1,13,2,13,3,13,4,13,5,13,6,13,7,13,8,13,9,13,10,13,11,13,12,13,13,13,14,13,15,13, +16,13,17,13,18,13,19,13,20,13,21,13,22,13,23,13,24,13,25,13,26,13,27,13,28,13,29,13,30,13,31,13,32,13,33,13,34,13,35,13,36,13,37,13,38,13,39,13,40,13,41,13,42,13,43,13,44,13,45,13,46,13,47,13,48,13,49,13,50,9,115,102,116,104,121,112,104,101,110,7,65, +109,97,99,114,111,110,7,97,109,97,99,114,111,110,6,65,98,114,101,118,101,6,97,98,114,101,118,101,7,65,111,103,111,110,101,107,7,97,111,103,111,110,101,107,11,67,99,105,114,99,117,109,102,108,101,120,11,99,99,105,114,99,117,109,102,108,101,120,10,67,100, +111,116,97,99,99,101,110,116,10,99,100,111,116,97,99,99,101,110,116,6,68,99,97,114,111,110,6,100,99,97,114,111,110,6,68,99,114,111,97,116,7,69,109,97,99,114,111,110,7,101,109,97,99,114,111,110,6,69,98,114,101,118,101,6,101,98,114,101,118,101,10,69,100, +111,116,97,99,99,101,110,116,10,101,100,111,116,97,99,99,101,110,116,7,69,111,103,111,110,101,107,7,101,111,103,111,110,101,107,6,69,99,97,114,111,110,6,101,99,97,114,111,110,11,71,99,105,114,99,117,109,102,108,101,120,11,103,99,105,114,99,117,109,102, +108,101,120,10,71,100,111,116,97,99,99,101,110,116,10,103,100,111,116,97,99,99,101,110,116,12,71,99,111,109,109,97,97,99,99,101,110,116,12,103,99,111,109,109,97,97,99,99,101,110,116,11,72,99,105,114,99,117,109,102,108,101,120,11,104,99,105,114,99,117, +109,102,108,101,120,4,72,98,97,114,4,104,98,97,114,6,73,116,105,108,100,101,6,105,116,105,108,100,101,7,73,109,97,99,114,111,110,7,105,109,97,99,114,111,110,6,73,98,114,101,118,101,6,105,98,114,101,118,101,7,73,111,103,111,110,101,107,7,105,111,103,111, +110,101,107,2,73,74,2,105,106,11,74,99,105,114,99,117,109,102,108,101,120,11,106,99,105,114,99,117,109,102,108,101,120,12,75,99,111,109,109,97,97,99,99,101,110,116,12,107,99,111,109,109,97,97,99,99,101,110,116,12,107,103,114,101,101,110,108,97,110,100, +105,99,6,76,97,99,117,116,101,6,108,97,99,117,116,101,12,76,99,111,109,109,97,97,99,99,101,110,116,12,108,99,111,109,109,97,97,99,99,101,110,116,6,76,99,97,114,111,110,6,108,99,97,114,111,110,4,76,100,111,116,4,108,100,111,116,6,78,97,99,117,116,101, +6,110,97,99,117,116,101,12,78,99,111,109,109,97,97,99,99,101,110,116,12,110,99,111,109,109,97,97,99,99,101,110,116,6,78,99,97,114,111,110,6,110,99,97,114,111,110,11,110,97,112,111,115,116,114,111,112,104,101,3,69,110,103,3,101,110,103,7,79,109,97,99, +114,111,110,7,111,109,97,99,114,111,110,6,79,98,114,101,118,101,6,111,98,114,101,118,101,13,79,104,117,110,103,97,114,117,109,108,97,117,116,13,111,104,117,110,103,97,114,117,109,108,97,117,116,6,82,97,99,117,116,101,6,114,97,99,117,116,101,12,82,99, +111,109,109,97,97,99,99,101,110,116,12,114,99,111,109,109,97,97,99,99,101,110,116,6,82,99,97,114,111,110,6,114,99,97,114,111,110,6,83,97,99,117,116,101,6,115,97,99,117,116,101,11,83,99,105,114,99,117,109,102,108,101,120,11,115,99,105,114,99,117,109,102, +108,101,120,12,84,99,111,109,109,97,97,99,99,101,110,116,12,116,99,111,109,109,97,97,99,99,101,110,116,6,84,99,97,114,111,110,6,116,99,97,114,111,110,4,84,98,97,114,4,116,98,97,114,6,85,116,105,108,100,101,6,117,116,105,108,100,101,7,85,109,97,99,114, +111,110,7,117,109,97,99,114,111,110,6,85,98,114,101,118,101,6,117,98,114,101,118,101,5,85,114,105,110,103,5,117,114,105,110,103,13,85,104,117,110,103,97,114,117,109,108,97,117,116,13,117,104,117,110,103,97,114,117,109,108,97,117,116,7,85,111,103,111, +110,101,107,7,117,111,103,111,110,101,107,11,87,99,105,114,99,117,109,102,108,101,120,11,119,99,105,114,99,117,109,102,108,101,120,11,89,99,105,114,99,117,109,102,108,101,120,11,121,99,105,114,99,117,109,102,108,101,120,6,90,97,99,117,116,101,6,122,97, +99,117,116,101,10,90,100,111,116,97,99,99,101,110,116,10,122,100,111,116,97,99,99,101,110,116,5,108,111,110,103,115,7,117,110,105,48,49,56,48,7,117,110,105,48,49,56,49,7,117,110,105,48,49,56,50,7,117,110,105,48,49,56,51,7,117,110,105,48,49,56,52,7,117, +110,105,48,49,56,53,7,117,110,105,48,49,56,54,7,117,110,105,48,49,56,55,7,117,110,105,48,49,56,56,7,117,110,105,48,49,56,57,7,117,110,105,48,49,56,65,7,117,110,105,48,49,56,66,7,117,110,105,48,49,56,67,7,117,110,105,48,49,56,68,7,117,110,105,48,49,56, +69,7,117,110,105,48,49,56,70,7,117,110,105,48,49,57,48,7,117,110,105,48,49,57,49,7,117,110,105,48,49,57,51,7,117,110,105,48,49,57,52,7,117,110,105,48,49,57,53,7,117,110,105,48,49,57,54,7,117,110,105,48,49,57,55,7,117,110,105,48,49,57,56,7,117,110,105, +48,49,57,57,7,117,110,105,48,49,57,65,7,117,110,105,48,49,57,66,7,117,110,105,48,49,57,67,7,117,110,105,48,49,57,68,7,117,110,105,48,49,57,69,7,117,110,105,48,49,57,70,5,79,104,111,114,110,5,111,104,111,114,110,7,117,110,105,48,49,65,50,7,117,110,105, +48,49,65,51,7,117,110,105,48,49,65,52,7,117,110,105,48,49,65,53,7,117,110,105,48,49,65,54,7,117,110,105,48,49,65,55,7,117,110,105,48,49,65,56,7,117,110,105,48,49,65,57,7,117,110,105,48,49,65,65,7,117,110,105,48,49,65,66,7,117,110,105,48,49,65,67,7,117, +110,105,48,49,65,68,7,117,110,105,48,49,65,69,5,85,104,111,114,110,5,117,104,111,114,110,7,117,110,105,48,49,66,49,7,117,110,105,48,49,66,50,7,117,110,105,48,49,66,51,7,117,110,105,48,49,66,52,7,117,110,105,48,49,66,53,7,117,110,105,48,49,66,54,7,117, +110,105,48,49,66,55,7,117,110,105,48,49,66,56,7,117,110,105,48,49,66,57,7,117,110,105,48,49,66,65,7,117,110,105,48,49,66,66,7,117,110,105,48,49,66,67,7,117,110,105,48,49,66,68,7,117,110,105,48,49,66,69,7,117,110,105,48,49,66,70,7,117,110,105,48,49,67, +48,7,117,110,105,48,49,67,49,7,117,110,105,48,49,67,50,7,117,110,105,48,49,67,51,7,117,110,105,48,49,67,68,7,117,110,105,48,49,67,69,7,117,110,105,48,49,67,70,7,117,110,105,48,49,68,48,7,117,110,105,48,49,68,49,7,117,110,105,48,49,68,50,7,117,110,105, +48,49,68,51,7,117,110,105,48,49,68,52,7,117,110,105,48,49,68,53,7,117,110,105,48,49,68,54,7,117,110,105,48,49,68,55,7,117,110,105,48,49,68,56,7,117,110,105,48,49,68,57,7,117,110,105,48,49,68,65,7,117,110,105,48,49,68,66,7,117,110,105,48,49,68,67,7,117, +110,105,48,49,68,68,7,117,110,105,48,49,68,69,7,117,110,105,48,49,68,70,7,117,110,105,48,49,69,48,7,117,110,105,48,49,69,49,7,117,110,105,48,49,69,50,7,117,110,105,48,49,69,51,6,71,99,97,114,111,110,6,103,99,97,114,111,110,7,117,110,105,48,49,69,56,7, +117,110,105,48,49,69,57,7,117,110,105,48,49,69,65,7,117,110,105,48,49,69,66,7,117,110,105,48,49,69,67,7,117,110,105,48,49,69,68,7,117,110,105,48,49,69,69,7,117,110,105,48,49,69,70,7,117,110,105,48,49,70,48,7,117,110,105,48,49,70,52,7,117,110,105,48,49, +70,53,7,117,110,105,48,49,70,54,7,117,110,105,48,49,70,56,7,117,110,105,48,49,70,57,7,65,69,97,99,117,116,101,7,97,101,97,99,117,116,101,11,79,115,108,97,115,104,97,99,117,116,101,11,111,115,108,97,115,104,97,99,117,116,101,7,117,110,105,48,50,48,48, +7,117,110,105,48,50,48,49,7,117,110,105,48,50,48,50,7,117,110,105,48,50,48,51,7,117,110,105,48,50,48,52,7,117,110,105,48,50,48,53,7,117,110,105,48,50,48,54,7,117,110,105,48,50,48,55,7,117,110,105,48,50,48,56,7,117,110,105,48,50,48,57,7,117,110,105,48, +50,48,65,7,117,110,105,48,50,48,66,7,117,110,105,48,50,48,67,7,117,110,105,48,50,48,68,7,117,110,105,48,50,48,69,7,117,110,105,48,50,48,70,7,117,110,105,48,50,49,48,7,117,110,105,48,50,49,49,7,117,110,105,48,50,49,50,7,117,110,105,48,50,49,51,7,117,110, +105,48,50,49,52,7,117,110,105,48,50,49,53,7,117,110,105,48,50,49,54,7,117,110,105,48,50,49,55,12,83,99,111,109,109,97,97,99,99,101,110,116,12,115,99,111,109,109,97,97,99,99,101,110,116,7,117,110,105,48,50,49,65,7,117,110,105,48,50,49,66,7,117,110,105, +48,50,49,67,7,117,110,105,48,50,49,68,7,117,110,105,48,50,49,69,7,117,110,105,48,50,49,70,7,117,110,105,48,50,50,48,7,117,110,105,48,50,50,49,7,117,110,105,48,50,50,52,7,117,110,105,48,50,50,53,7,117,110,105,48,50,50,54,7,117,110,105,48,50,50,55,7,117, +110,105,48,50,50,56,7,117,110,105,48,50,50,57,7,117,110,105,48,50,50,65,7,117,110,105,48,50,50,66,7,117,110,105,48,50,50,67,7,117,110,105,48,50,50,68,7,117,110,105,48,50,50,69,7,117,110,105,48,50,50,70,7,117,110,105,48,50,51,48,7,117,110,105,48,50,51, +49,7,117,110,105,48,50,51,50,7,117,110,105,48,50,51,51,7,117,110,105,48,50,51,52,7,117,110,105,48,50,51,53,7,117,110,105,48,50,51,54,8,100,111,116,108,101,115,115,106,7,117,110,105,48,50,51,56,7,117,110,105,48,50,51,57,7,117,110,105,48,50,51,65,7,117, +110,105,48,50,51,66,7,117,110,105,48,50,51,67,7,117,110,105,48,50,51,68,7,117,110,105,48,50,51,69,7,117,110,105,48,50,51,70,7,117,110,105,48,50,52,48,7,117,110,105,48,50,52,49,7,117,110,105,48,50,52,51,7,117,110,105,48,50,52,52,7,117,110,105,48,50,52, +53,7,117,110,105,48,50,52,67,7,117,110,105,48,50,52,68,7,117,110,105,48,50,53,48,7,117,110,105,48,50,53,49,7,117,110,105,48,50,53,50,7,117,110,105,48,50,53,51,7,117,110,105,48,50,53,52,7,117,110,105,48,50,53,53,7,117,110,105,48,50,53,54,7,117,110,105, +48,50,53,55,7,117,110,105,48,50,53,56,7,117,110,105,48,50,53,57,7,117,110,105,48,50,53,65,7,117,110,105,48,50,53,66,7,117,110,105,48,50,53,67,7,117,110,105,48,50,53,68,7,117,110,105,48,50,53,69,7,117,110,105,48,50,53,70,7,117,110,105,48,50,54,48,7,117, +110,105,48,50,54,49,7,117,110,105,48,50,54,50,7,117,110,105,48,50,54,51,7,117,110,105,48,50,54,52,7,117,110,105,48,50,54,53,7,117,110,105,48,50,54,54,7,117,110,105,48,50,54,55,7,117,110,105,48,50,54,56,7,117,110,105,48,50,54,57,7,117,110,105,48,50,54, +65,7,117,110,105,48,50,54,66,7,117,110,105,48,50,54,67,7,117,110,105,48,50,54,68,7,117,110,105,48,50,54,69,7,117,110,105,48,50,54,70,7,117,110,105,48,50,55,48,7,117,110,105,48,50,55,49,7,117,110,105,48,50,55,50,7,117,110,105,48,50,55,51,7,117,110,105, +48,50,55,52,7,117,110,105,48,50,55,53,7,117,110,105,48,50,55,54,7,117,110,105,48,50,55,55,7,117,110,105,48,50,55,56,7,117,110,105,48,50,55,57,7,117,110,105,48,50,55,65,7,117,110,105,48,50,55,66,7,117,110,105,48,50,55,67,7,117,110,105,48,50,55,68,7,117, +110,105,48,50,55,69,7,117,110,105,48,50,55,70,7,117,110,105,48,50,56,48,7,117,110,105,48,50,56,49,7,117,110,105,48,50,56,50,7,117,110,105,48,50,56,51,7,117,110,105,48,50,56,52,7,117,110,105,48,50,56,53,7,117,110,105,48,50,56,54,7,117,110,105,48,50,56, +55,7,117,110,105,48,50,56,56,7,117,110,105,48,50,56,57,7,117,110,105,48,50,56,65,7,117,110,105,48,50,56,66,7,117,110,105,48,50,56,67,7,117,110,105,48,50,56,68,7,117,110,105,48,50,56,69,7,117,110,105,48,50,56,70,7,117,110,105,48,50,57,48,7,117,110,105, +48,50,57,49,7,117,110,105,48,50,57,50,7,117,110,105,48,50,57,51,7,117,110,105,48,50,57,52,7,117,110,105,48,50,57,53,7,117,110,105,48,50,57,54,7,117,110,105,48,50,57,55,7,117,110,105,48,50,57,56,7,117,110,105,48,50,57,57,7,117,110,105,48,50,57,65,7,117, +110,105,48,50,57,66,7,117,110,105,48,50,57,67,7,117,110,105,48,50,57,68,7,117,110,105,48,50,57,69,7,117,110,105,48,50,57,70,7,117,110,105,48,50,65,48,7,117,110,105,48,50,65,49,7,117,110,105,48,50,65,50,7,117,110,105,48,50,65,51,7,117,110,105,48,50,65, +52,7,117,110,105,48,50,65,53,7,117,110,105,48,50,65,54,7,117,110,105,48,50,65,55,7,117,110,105,48,50,65,56,7,117,110,105,48,50,65,57,7,117,110,105,48,50,65,65,7,117,110,105,48,50,65,66,7,117,110,105,48,50,65,67,7,117,110,105,48,50,65,68,7,117,110,105, +48,50,65,69,7,117,110,105,48,50,65,70,7,117,110,105,48,50,66,48,7,117,110,105,48,50,66,49,7,117,110,105,48,50,66,50,7,117,110,105,48,50,66,51,7,117,110,105,48,50,66,52,7,117,110,105,48,50,66,53,7,117,110,105,48,50,66,54,7,117,110,105,48,50,66,55,7,117, +110,105,48,50,66,56,7,117,110,105,48,50,66,57,7,117,110,105,48,50,66,66,7,117,110,105,48,50,66,67,7,117,110,105,48,50,66,68,7,117,110,105,48,50,66,69,7,117,110,105,48,50,66,70,7,117,110,105,48,50,67,48,7,117,110,105,48,50,67,49,7,117,110,105,48,50,67, +56,7,117,110,105,48,50,67,57,7,117,110,105,48,50,67,67,7,117,110,105,48,50,67,68,7,117,110,105,48,50,67,69,7,117,110,105,48,50,67,70,7,117,110,105,48,50,68,48,7,117,110,105,48,50,68,49,7,117,110,105,48,50,68,50,7,117,110,105,48,50,68,51,7,117,110,105, +48,50,68,54,7,117,110,105,48,50,68,55,7,117,110,105,48,50,68,69,7,117,110,105,48,50,69,48,7,117,110,105,48,50,69,49,7,117,110,105,48,50,69,50,7,117,110,105,48,50,69,51,7,117,110,105,48,50,69,52,7,117,110,105,48,50,69,53,7,117,110,105,48,50,69,54,7,117, +110,105,48,50,69,55,7,117,110,105,48,50,69,56,7,117,110,105,48,50,69,57,7,117,110,105,48,50,69,69,7,117,110,105,48,50,70,51,9,103,114,97,118,101,99,111,109,98,9,97,99,117,116,101,99,111,109,98,7,117,110,105,48,51,48,50,9,116,105,108,100,101,99,111,109, +98,7,117,110,105,48,51,48,52,7,117,110,105,48,51,48,53,7,117,110,105,48,51,48,54,7,117,110,105,48,51,48,55,7,117,110,105,48,51,48,56,13,104,111,111,107,97,98,111,118,101,99,111,109,98,7,117,110,105,48,51,48,65,7,117,110,105,48,51,48,66,7,117,110,105, +48,51,48,67,7,117,110,105,48,51,48,68,7,117,110,105,48,51,48,69,7,117,110,105,48,51,48,70,7,117,110,105,48,51,49,48,7,117,110,105,48,51,49,49,7,117,110,105,48,51,49,50,7,117,110,105,48,51,49,51,7,117,110,105,48,51,49,52,7,117,110,105,48,51,49,53,7,117, +110,105,48,51,49,54,7,117,110,105,48,51,49,55,7,117,110,105,48,51,49,56,7,117,110,105,48,51,49,57,7,117,110,105,48,51,49,65,7,117,110,105,48,51,49,66,7,117,110,105,48,51,49,67,7,117,110,105,48,51,49,68,7,117,110,105,48,51,49,69,7,117,110,105,48,51,49, +70,7,117,110,105,48,51,50,48,7,117,110,105,48,51,50,49,7,117,110,105,48,51,50,50,12,100,111,116,98,101,108,111,119,99,111,109,98,7,117,110,105,48,51,50,52,7,117,110,105,48,51,50,53,7,117,110,105,48,51,50,54,7,117,110,105,48,51,50,55,7,117,110,105,48, +51,50,56,7,117,110,105,48,51,50,57,7,117,110,105,48,51,50,65,7,117,110,105,48,51,50,66,7,117,110,105,48,51,50,67,7,117,110,105,48,51,50,68,7,117,110,105,48,51,50,69,7,117,110,105,48,51,50,70,7,117,110,105,48,51,51,48,7,117,110,105,48,51,51,49,7,117,110, +105,48,51,51,50,7,117,110,105,48,51,51,51,7,117,110,105,48,51,51,52,7,117,110,105,48,51,51,53,7,117,110,105,48,51,51,54,7,117,110,105,48,51,51,55,7,117,110,105,48,51,51,56,7,117,110,105,48,51,51,57,7,117,110,105,48,51,51,65,7,117,110,105,48,51,51,66, +7,117,110,105,48,51,51,67,7,117,110,105,48,51,51,68,7,117,110,105,48,51,51,69,7,117,110,105,48,51,51,70,7,117,110,105,48,51,52,51,7,117,110,105,48,51,53,56,7,117,110,105,48,51,54,49,7,117,110,105,48,51,55,52,7,117,110,105,48,51,55,53,7,117,110,105,48, +51,55,54,7,117,110,105,48,51,55,55,7,117,110,105,48,51,55,65,7,117,110,105,48,51,55,66,7,117,110,105,48,51,55,67,7,117,110,105,48,51,55,68,7,117,110,105,48,51,55,69,7,117,110,105,48,51,55,70,5,116,111,110,111,115,13,100,105,101,114,101,115,105,115,116, +111,110,111,115,10,65,108,112,104,97,116,111,110,111,115,9,97,110,111,116,101,108,101,105,97,12,69,112,115,105,108,111,110,116,111,110,111,115,8,69,116,97,116,111,110,111,115,9,73,111,116,97,116,111,110,111,115,12,79,109,105,99,114,111,110,116,111,110, +111,115,12,85,112,115,105,108,111,110,116,111,110,111,115,10,79,109,101,103,97,116,111,110,111,115,17,105,111,116,97,100,105,101,114,101,115,105,115,116,111,110,111,115,5,65,108,112,104,97,4,66,101,116,97,5,71,97,109,109,97,7,117,110,105,48,51,57,52, +7,69,112,115,105,108,111,110,4,90,101,116,97,3,69,116,97,5,84,104,101,116,97,4,73,111,116,97,5,75,97,112,112,97,6,76,97,109,98,100,97,2,77,117,2,78,117,2,88,105,7,79,109,105,99,114,111,110,2,80,105,3,82,104,111,5,83,105,103,109,97,3,84,97,117,7,85,112, +115,105,108,111,110,3,80,104,105,3,67,104,105,3,80,115,105,12,73,111,116,97,100,105,101,114,101,115,105,115,15,85,112,115,105,108,111,110,100,105,101,114,101,115,105,115,10,97,108,112,104,97,116,111,110,111,115,12,101,112,115,105,108,111,110,116,111, +110,111,115,8,101,116,97,116,111,110,111,115,9,105,111,116,97,116,111,110,111,115,20,117,112,115,105,108,111,110,100,105,101,114,101,115,105,115,116,111,110,111,115,5,97,108,112,104,97,4,98,101,116,97,5,103,97,109,109,97,5,100,101,108,116,97,7,101,112, +115,105,108,111,110,4,122,101,116,97,3,101,116,97,5,116,104,101,116,97,4,105,111,116,97,5,107,97,112,112,97,6,108,97,109,98,100,97,7,117,110,105,48,51,66,67,2,110,117,2,120,105,7,111,109,105,99,114,111,110,3,114,104,111,6,115,105,103,109,97,49,5,115, +105,103,109,97,3,116,97,117,7,117,112,115,105,108,111,110,3,112,104,105,3,99,104,105,3,112,115,105,5,111,109,101,103,97,12,105,111,116,97,100,105,101,114,101,115,105,115,15,117,112,115,105,108,111,110,100,105,101,114,101,115,105,115,12,111,109,105,99, +114,111,110,116,111,110,111,115,12,117,112,115,105,108,111,110,116,111,110,111,115,10,111,109,101,103,97,116,111,110,111,115,7,117,110,105,48,51,68,48,6,116,104,101,116,97,49,8,85,112,115,105,108,111,110,49,7,117,110,105,48,51,68,51,7,117,110,105,48, +51,68,52,4,112,104,105,49,6,111,109,101,103,97,49,7,117,110,105,48,51,68,55,7,117,110,105,48,51,68,56,7,117,110,105,48,51,68,57,7,117,110,105,48,51,68,65,7,117,110,105,48,51,68,66,7,117,110,105,48,51,68,67,7,117,110,105,48,51,68,68,7,117,110,105,48,51, +68,69,7,117,110,105,48,51,68,70,7,117,110,105,48,51,69,48,7,117,110,105,48,51,69,49,7,117,110,105,48,51,70,48,7,117,110,105,48,51,70,49,7,117,110,105,48,51,70,50,7,117,110,105,48,51,70,51,7,117,110,105,48,51,70,52,7,117,110,105,48,51,70,53,7,117,110, +105,48,51,70,54,7,117,110,105,48,51,70,55,7,117,110,105,48,51,70,56,7,117,110,105,48,51,70,57,7,117,110,105,48,51,70,65,7,117,110,105,48,51,70,66,7,117,110,105,48,51,70,67,7,117,110,105,48,51,70,68,7,117,110,105,48,51,70,69,7,117,110,105,48,51,70,70, +7,117,110,105,48,52,48,48,7,117,110,105,48,52,48,49,7,117,110,105,48,52,48,50,7,117,110,105,48,52,48,51,7,117,110,105,48,52,48,52,7,117,110,105,48,52,48,53,7,117,110,105,48,52,48,54,7,117,110,105,48,52,48,55,7,117,110,105,48,52,48,56,7,117,110,105,48, +52,48,57,7,117,110,105,48,52,48,65,7,117,110,105,48,52,48,66,7,117,110,105,48,52,48,67,7,117,110,105,48,52,48,68,7,117,110,105,48,52,48,69,7,117,110,105,48,52,48,70,7,117,110,105,48,52,49,48,7,117,110,105,48,52,49,49,7,117,110,105,48,52,49,50,7,117,110, +105,48,52,49,51,7,117,110,105,48,52,49,52,7,117,110,105,48,52,49,53,7,117,110,105,48,52,49,54,7,117,110,105,48,52,49,55,7,117,110,105,48,52,49,56,7,117,110,105,48,52,49,57,7,117,110,105,48,52,49,65,7,117,110,105,48,52,49,66,7,117,110,105,48,52,49,67, +7,117,110,105,48,52,49,68,7,117,110,105,48,52,49,69,7,117,110,105,48,52,49,70,7,117,110,105,48,52,50,48,7,117,110,105,48,52,50,49,7,117,110,105,48,52,50,50,7,117,110,105,48,52,50,51,7,117,110,105,48,52,50,52,7,117,110,105,48,52,50,53,7,117,110,105,48, +52,50,54,7,117,110,105,48,52,50,55,7,117,110,105,48,52,50,56,7,117,110,105,48,52,50,57,7,117,110,105,48,52,50,65,7,117,110,105,48,52,50,66,7,117,110,105,48,52,50,67,7,117,110,105,48,52,50,68,7,117,110,105,48,52,50,69,7,117,110,105,48,52,50,70,7,117,110, +105,48,52,51,48,7,117,110,105,48,52,51,49,7,117,110,105,48,52,51,50,7,117,110,105,48,52,51,51,7,117,110,105,48,52,51,52,7,117,110,105,48,52,51,53,7,117,110,105,48,52,51,54,7,117,110,105,48,52,51,55,7,117,110,105,48,52,51,56,7,117,110,105,48,52,51,57, +7,117,110,105,48,52,51,65,7,117,110,105,48,52,51,66,7,117,110,105,48,52,51,67,7,117,110,105,48,52,51,68,7,117,110,105,48,52,51,69,7,117,110,105,48,52,51,70,7,117,110,105,48,52,52,48,7,117,110,105,48,52,52,49,7,117,110,105,48,52,52,50,7,117,110,105,48, +52,52,51,7,117,110,105,48,52,52,52,7,117,110,105,48,52,52,53,7,117,110,105,48,52,52,54,7,117,110,105,48,52,52,55,7,117,110,105,48,52,52,56,7,117,110,105,48,52,52,57,7,117,110,105,48,52,52,65,7,117,110,105,48,52,52,66,7,117,110,105,48,52,52,67,7,117,110, +105,48,52,52,68,7,117,110,105,48,52,52,69,7,117,110,105,48,52,52,70,7,117,110,105,48,52,53,48,7,117,110,105,48,52,53,49,7,117,110,105,48,52,53,50,7,117,110,105,48,52,53,51,7,117,110,105,48,52,53,52,7,117,110,105,48,52,53,53,7,117,110,105,48,52,53,54, +7,117,110,105,48,52,53,55,7,117,110,105,48,52,53,56,7,117,110,105,48,52,53,57,7,117,110,105,48,52,53,65,7,117,110,105,48,52,53,66,7,117,110,105,48,52,53,67,7,117,110,105,48,52,53,68,7,117,110,105,48,52,53,69,7,117,110,105,48,52,53,70,7,117,110,105,48, +52,54,50,7,117,110,105,48,52,54,51,7,117,110,105,48,52,55,50,7,117,110,105,48,52,55,51,7,117,110,105,48,52,57,48,7,117,110,105,48,52,57,49,7,117,110,105,48,52,57,50,7,117,110,105,48,52,57,51,7,117,110,105,48,52,57,52,7,117,110,105,48,52,57,53,7,117,110, +105,48,52,57,54,7,117,110,105,48,52,57,55,7,117,110,105,48,52,57,56,7,117,110,105,48,52,57,57,7,117,110,105,48,52,57,65,7,117,110,105,48,52,57,66,7,117,110,105,48,52,65,50,7,117,110,105,48,52,65,51,7,117,110,105,48,52,65,52,7,117,110,105,48,52,65,53, +7,117,110,105,48,52,65,65,7,117,110,105,48,52,65,66,7,117,110,105,48,52,65,67,7,117,110,105,48,52,65,68,7,117,110,105,48,52,65,69,7,117,110,105,48,52,65,70,7,117,110,105,48,52,66,48,7,117,110,105,48,52,66,49,7,117,110,105,48,52,66,50,7,117,110,105,48, +52,66,51,7,117,110,105,48,52,66,65,7,117,110,105,48,52,66,66,7,117,110,105,48,52,67,48,7,117,110,105,48,52,67,49,7,117,110,105,48,52,67,50,7,117,110,105,48,52,67,51,7,117,110,105,48,52,67,52,7,117,110,105,48,52,67,55,7,117,110,105,48,52,67,56,7,117,110, +105,48,52,67,66,7,117,110,105,48,52,67,67,7,117,110,105,48,52,67,70,7,117,110,105,48,52,68,48,7,117,110,105,48,52,68,49,7,117,110,105,48,52,68,50,7,117,110,105,48,52,68,51,7,117,110,105,48,52,68,52,7,117,110,105,48,52,68,53,7,117,110,105,48,52,68,54, +7,117,110,105,48,52,68,55,7,117,110,105,48,52,68,56,7,117,110,105,48,52,68,57,7,117,110,105,48,52,68,65,7,117,110,105,48,52,68,66,7,117,110,105,48,52,68,67,7,117,110,105,48,52,68,68,7,117,110,105,48,52,68,69,7,117,110,105,48,52,68,70,7,117,110,105,48, +52,69,48,7,117,110,105,48,52,69,49,7,117,110,105,48,52,69,50,7,117,110,105,48,52,69,51,7,117,110,105,48,52,69,52,7,117,110,105,48,52,69,53,7,117,110,105,48,52,69,54,7,117,110,105,48,52,69,55,7,117,110,105,48,52,69,56,7,117,110,105,48,52,69,57,7,117,110, +105,48,52,69,65,7,117,110,105,48,52,69,66,7,117,110,105,48,52,69,67,7,117,110,105,48,52,69,68,7,117,110,105,48,52,69,69,7,117,110,105,48,52,69,70,7,117,110,105,48,52,70,48,7,117,110,105,48,52,70,49,7,117,110,105,48,52,70,50,7,117,110,105,48,52,70,51, +7,117,110,105,48,52,70,52,7,117,110,105,48,52,70,53,7,117,110,105,48,52,70,54,7,117,110,105,48,52,70,55,7,117,110,105,48,52,70,56,7,117,110,105,48,52,70,57,7,117,110,105,48,53,49,48,7,117,110,105,48,53,49,49,7,117,110,105,48,53,49,65,7,117,110,105,48, +53,49,66,7,117,110,105,48,53,49,67,7,117,110,105,48,53,49,68,7,117,110,105,48,53,51,49,7,117,110,105,48,53,51,50,7,117,110,105,48,53,51,51,7,117,110,105,48,53,51,52,7,117,110,105,48,53,51,53,7,117,110,105,48,53,51,54,7,117,110,105,48,53,51,55,7,117,110, +105,48,53,51,56,7,117,110,105,48,53,51,57,7,117,110,105,48,53,51,65,7,117,110,105,48,53,51,66,7,117,110,105,48,53,51,67,7,117,110,105,48,53,51,68,7,117,110,105,48,53,51,69,7,117,110,105,48,53,51,70,7,117,110,105,48,53,52,48,7,117,110,105,48,53,52,49, +7,117,110,105,48,53,52,50,7,117,110,105,48,53,52,51,7,117,110,105,48,53,52,52,7,117,110,105,48,53,52,53,7,117,110,105,48,53,52,54,7,117,110,105,48,53,52,55,7,117,110,105,48,53,52,56,7,117,110,105,48,53,52,57,7,117,110,105,48,53,52,65,7,117,110,105,48, +53,52,66,7,117,110,105,48,53,52,67,7,117,110,105,48,53,52,68,7,117,110,105,48,53,52,69,7,117,110,105,48,53,52,70,7,117,110,105,48,53,53,48,7,117,110,105,48,53,53,49,7,117,110,105,48,53,53,50,7,117,110,105,48,53,53,51,7,117,110,105,48,53,53,52,7,117,110, +105,48,53,53,53,7,117,110,105,48,53,53,54,7,117,110,105,48,53,53,57,7,117,110,105,48,53,53,65,7,117,110,105,48,53,53,66,7,117,110,105,48,53,53,67,7,117,110,105,48,53,53,68,7,117,110,105,48,53,53,69,7,117,110,105,48,53,53,70,7,117,110,105,48,53,54,49, +7,117,110,105,48,53,54,50,7,117,110,105,48,53,54,51,7,117,110,105,48,53,54,52,7,117,110,105,48,53,54,53,7,117,110,105,48,53,54,54,7,117,110,105,48,53,54,55,7,117,110,105,48,53,54,56,7,117,110,105,48,53,54,57,7,117,110,105,48,53,54,65,7,117,110,105,48, +53,54,66,7,117,110,105,48,53,54,67,7,117,110,105,48,53,54,68,7,117,110,105,48,53,54,69,7,117,110,105,48,53,54,70,7,117,110,105,48,53,55,48,7,117,110,105,48,53,55,49,7,117,110,105,48,53,55,50,7,117,110,105,48,53,55,51,7,117,110,105,48,53,55,52,7,117,110, +105,48,53,55,53,7,117,110,105,48,53,55,54,7,117,110,105,48,53,55,55,7,117,110,105,48,53,55,56,7,117,110,105,48,53,55,57,7,117,110,105,48,53,55,65,7,117,110,105,48,53,55,66,7,117,110,105,48,53,55,67,7,117,110,105,48,53,55,68,7,117,110,105,48,53,55,69, +7,117,110,105,48,53,55,70,7,117,110,105,48,53,56,48,7,117,110,105,48,53,56,49,7,117,110,105,48,53,56,50,7,117,110,105,48,53,56,51,7,117,110,105,48,53,56,52,7,117,110,105,48,53,56,53,7,117,110,105,48,53,56,54,7,117,110,105,48,53,56,55,7,117,110,105,48, +53,56,57,7,117,110,105,48,53,56,65,7,117,110,105,48,54,48,54,7,117,110,105,48,54,48,55,7,117,110,105,48,54,48,57,7,117,110,105,48,54,48,65,7,117,110,105,48,54,48,67,7,117,110,105,48,54,49,53,7,117,110,105,48,54,49,66,7,117,110,105,48,54,49,70,7,117,110, +105,48,54,50,49,7,117,110,105,48,54,50,50,7,117,110,105,48,54,50,51,7,117,110,105,48,54,50,52,7,117,110,105,48,54,50,53,7,117,110,105,48,54,50,54,7,117,110,105,48,54,50,55,7,117,110,105,48,54,50,56,7,117,110,105,48,54,50,57,7,117,110,105,48,54,50,65, +7,117,110,105,48,54,50,66,7,117,110,105,48,54,50,67,7,117,110,105,48,54,50,68,7,117,110,105,48,54,50,69,7,117,110,105,48,54,50,70,7,117,110,105,48,54,51,48,7,117,110,105,48,54,51,49,7,117,110,105,48,54,51,50,7,117,110,105,48,54,51,51,7,117,110,105,48, +54,51,52,7,117,110,105,48,54,51,53,7,117,110,105,48,54,51,54,7,117,110,105,48,54,51,55,7,117,110,105,48,54,51,56,7,117,110,105,48,54,51,57,7,117,110,105,48,54,51,65,7,117,110,105,48,54,52,48,7,117,110,105,48,54,52,49,7,117,110,105,48,54,52,50,7,117,110, +105,48,54,52,51,7,117,110,105,48,54,52,52,7,117,110,105,48,54,52,53,7,117,110,105,48,54,52,54,7,117,110,105,48,54,52,55,7,117,110,105,48,54,52,56,7,117,110,105,48,54,52,57,7,117,110,105,48,54,52,65,7,117,110,105,48,54,52,66,7,117,110,105,48,54,52,67, +7,117,110,105,48,54,52,68,7,117,110,105,48,54,52,69,7,117,110,105,48,54,52,70,7,117,110,105,48,54,53,48,7,117,110,105,48,54,53,49,7,117,110,105,48,54,53,50,7,117,110,105,48,54,53,51,7,117,110,105,48,54,53,52,7,117,110,105,48,54,53,53,7,117,110,105,48, +54,53,65,7,117,110,105,48,54,54,48,7,117,110,105,48,54,54,49,7,117,110,105,48,54,54,50,7,117,110,105,48,54,54,51,7,117,110,105,48,54,54,52,7,117,110,105,48,54,54,53,7,117,110,105,48,54,54,54,7,117,110,105,48,54,54,55,7,117,110,105,48,54,54,56,7,117,110, +105,48,54,54,57,7,117,110,105,48,54,54,65,7,117,110,105,48,54,54,66,7,117,110,105,48,54,54,67,7,117,110,105,48,54,54,68,7,117,110,105,48,54,55,52,7,117,110,105,48,54,55,57,7,117,110,105,48,54,55,65,7,117,110,105,48,54,55,66,7,117,110,105,48,54,55,69, +7,117,110,105,48,54,55,70,7,117,110,105,48,54,56,48,7,117,110,105,48,54,56,51,7,117,110,105,48,54,56,52,7,117,110,105,48,54,56,54,7,117,110,105,48,54,56,55,7,117,110,105,48,54,57,49,7,117,110,105,48,54,57,56,7,117,110,105,48,54,65,52,7,117,110,105,48, +54,65,57,7,117,110,105,48,54,65,70,7,117,110,105,48,54,66,69,7,117,110,105,48,54,67,67,7,117,110,105,48,54,70,48,7,117,110,105,48,54,70,49,7,117,110,105,48,54,70,50,7,117,110,105,48,54,70,51,7,117,110,105,48,54,70,52,7,117,110,105,48,54,70,53,7,117,110, +105,48,54,70,54,7,117,110,105,48,54,70,55,7,117,110,105,48,54,70,56,7,117,110,105,48,54,70,57,7,117,110,105,48,69,51,70,7,117,110,105,48,69,56,49,7,117,110,105,48,69,56,50,7,117,110,105,48,69,56,52,7,117,110,105,48,69,56,55,7,117,110,105,48,69,56,56, +7,117,110,105,48,69,56,65,7,117,110,105,48,69,56,68,7,117,110,105,48,69,57,52,7,117,110,105,48,69,57,53,7,117,110,105,48,69,57,54,7,117,110,105,48,69,57,55,7,117,110,105,48,69,57,57,7,117,110,105,48,69,57,65,7,117,110,105,48,69,57,66,7,117,110,105,48, +69,57,67,7,117,110,105,48,69,57,68,7,117,110,105,48,69,57,69,7,117,110,105,48,69,57,70,7,117,110,105,48,69,65,49,7,117,110,105,48,69,65,50,7,117,110,105,48,69,65,51,7,117,110,105,48,69,65,53,7,117,110,105,48,69,65,55,7,117,110,105,48,69,65,65,7,117,110, +105,48,69,65,66,7,117,110,105,48,69,65,68,7,117,110,105,48,69,65,69,7,117,110,105,48,69,65,70,7,117,110,105,48,69,66,48,7,117,110,105,48,69,66,49,7,117,110,105,48,69,66,50,7,117,110,105,48,69,66,51,7,117,110,105,48,69,66,52,7,117,110,105,48,69,66,53, +7,117,110,105,48,69,66,54,7,117,110,105,48,69,66,55,7,117,110,105,48,69,66,56,7,117,110,105,48,69,66,57,7,117,110,105,48,69,66,66,7,117,110,105,48,69,66,67,7,117,110,105,48,69,67,56,7,117,110,105,48,69,67,57,7,117,110,105,48,69,67,65,7,117,110,105,48, +69,67,66,7,117,110,105,48,69,67,67,7,117,110,105,48,69,67,68,7,117,110,105,49,48,68,48,7,117,110,105,49,48,68,49,7,117,110,105,49,48,68,50,7,117,110,105,49,48,68,51,7,117,110,105,49,48,68,52,7,117,110,105,49,48,68,53,7,117,110,105,49,48,68,54,7,117,110, +105,49,48,68,55,7,117,110,105,49,48,68,56,7,117,110,105,49,48,68,57,7,117,110,105,49,48,68,65,7,117,110,105,49,48,68,66,7,117,110,105,49,48,68,67,7,117,110,105,49,48,68,68,7,117,110,105,49,48,68,69,7,117,110,105,49,48,68,70,7,117,110,105,49,48,69,48, +7,117,110,105,49,48,69,49,7,117,110,105,49,48,69,50,7,117,110,105,49,48,69,51,7,117,110,105,49,48,69,52,7,117,110,105,49,48,69,53,7,117,110,105,49,48,69,54,7,117,110,105,49,48,69,55,7,117,110,105,49,48,69,56,7,117,110,105,49,48,69,57,7,117,110,105,49, +48,69,65,7,117,110,105,49,48,69,66,7,117,110,105,49,48,69,67,7,117,110,105,49,48,69,68,7,117,110,105,49,48,69,69,7,117,110,105,49,48,69,70,7,117,110,105,49,48,70,48,7,117,110,105,49,48,70,49,7,117,110,105,49,48,70,50,7,117,110,105,49,48,70,51,7,117,110, +105,49,48,70,52,7,117,110,105,49,48,70,53,7,117,110,105,49,48,70,54,7,117,110,105,49,48,70,55,7,117,110,105,49,48,70,56,7,117,110,105,49,48,70,57,7,117,110,105,49,48,70,65,7,117,110,105,49,48,70,66,7,117,110,105,49,48,70,67,7,117,110,105,49,68,48,50, +7,117,110,105,49,68,48,56,7,117,110,105,49,68,48,57,7,117,110,105,49,68,49,52,7,117,110,105,49,68,49,54,7,117,110,105,49,68,49,55,7,117,110,105,49,68,49,68,7,117,110,105,49,68,49,69,7,117,110,105,49,68,49,70,7,117,110,105,49,68,50,67,7,117,110,105,49, +68,50,68,7,117,110,105,49,68,50,69,7,117,110,105,49,68,51,48,7,117,110,105,49,68,51,49,7,117,110,105,49,68,51,50,7,117,110,105,49,68,51,51,7,117,110,105,49,68,51,52,7,117,110,105,49,68,51,53,7,117,110,105,49,68,51,54,7,117,110,105,49,68,51,55,7,117,110, +105,49,68,51,56,7,117,110,105,49,68,51,57,7,117,110,105,49,68,51,65,7,117,110,105,49,68,51,66,7,117,110,105,49,68,51,67,7,117,110,105,49,68,51,69,7,117,110,105,49,68,51,70,7,117,110,105,49,68,52,48,7,117,110,105,49,68,52,49,7,117,110,105,49,68,52,50, +7,117,110,105,49,68,52,51,7,117,110,105,49,68,52,52,7,117,110,105,49,68,52,53,7,117,110,105,49,68,52,54,7,117,110,105,49,68,52,55,7,117,110,105,49,68,52,56,7,117,110,105,49,68,52,57,7,117,110,105,49,68,52,65,7,117,110,105,49,68,52,66,7,117,110,105,49, +68,52,67,7,117,110,105,49,68,52,68,7,117,110,105,49,68,52,69,7,117,110,105,49,68,52,70,7,117,110,105,49,68,53,48,7,117,110,105,49,68,53,49,7,117,110,105,49,68,53,50,7,117,110,105,49,68,53,51,7,117,110,105,49,68,53,52,7,117,110,105,49,68,53,53,7,117,110, +105,49,68,53,54,7,117,110,105,49,68,53,55,7,117,110,105,49,68,53,56,7,117,110,105,49,68,53,57,7,117,110,105,49,68,53,65,7,117,110,105,49,68,53,66,7,117,110,105,49,68,54,50,7,117,110,105,49,68,54,51,7,117,110,105,49,68,54,52,7,117,110,105,49,68,54,53, +7,117,110,105,49,68,55,55,7,117,110,105,49,68,55,56,7,117,110,105,49,68,55,66,7,117,110,105,49,68,56,53,7,117,110,105,49,68,57,66,7,117,110,105,49,68,57,67,7,117,110,105,49,68,57,68,7,117,110,105,49,68,57,69,7,117,110,105,49,68,57,70,7,117,110,105,49, +68,65,48,7,117,110,105,49,68,65,49,7,117,110,105,49,68,65,50,7,117,110,105,49,68,65,51,7,117,110,105,49,68,65,52,7,117,110,105,49,68,65,53,7,117,110,105,49,68,65,54,7,117,110,105,49,68,65,55,7,117,110,105,49,68,65,56,7,117,110,105,49,68,65,57,7,117,110, +105,49,68,65,65,7,117,110,105,49,68,65,66,7,117,110,105,49,68,65,67,7,117,110,105,49,68,65,68,7,117,110,105,49,68,65,69,7,117,110,105,49,68,65,70,7,117,110,105,49,68,66,48,7,117,110,105,49,68,66,49,7,117,110,105,49,68,66,50,7,117,110,105,49,68,66,51, +7,117,110,105,49,68,66,52,7,117,110,105,49,68,66,53,7,117,110,105,49,68,66,54,7,117,110,105,49,68,66,55,7,117,110,105,49,68,66,57,7,117,110,105,49,68,66,65,7,117,110,105,49,68,66,66,7,117,110,105,49,68,66,67,7,117,110,105,49,68,66,68,7,117,110,105,49, +68,66,69,7,117,110,105,49,68,66,70,7,117,110,105,49,69,48,48,7,117,110,105,49,69,48,49,7,117,110,105,49,69,48,50,7,117,110,105,49,69,48,51,7,117,110,105,49,69,48,52,7,117,110,105,49,69,48,53,7,117,110,105,49,69,48,54,7,117,110,105,49,69,48,55,7,117,110, +105,49,69,48,56,7,117,110,105,49,69,48,57,7,117,110,105,49,69,48,65,7,117,110,105,49,69,48,66,7,117,110,105,49,69,48,67,7,117,110,105,49,69,48,68,7,117,110,105,49,69,48,69,7,117,110,105,49,69,48,70,7,117,110,105,49,69,49,48,7,117,110,105,49,69,49,49, +7,117,110,105,49,69,49,50,7,117,110,105,49,69,49,51,7,117,110,105,49,69,49,56,7,117,110,105,49,69,49,57,7,117,110,105,49,69,49,65,7,117,110,105,49,69,49,66,7,117,110,105,49,69,49,67,7,117,110,105,49,69,49,68,7,117,110,105,49,69,49,69,7,117,110,105,49, +69,49,70,7,117,110,105,49,69,50,48,7,117,110,105,49,69,50,49,7,117,110,105,49,69,50,50,7,117,110,105,49,69,50,51,7,117,110,105,49,69,50,52,7,117,110,105,49,69,50,53,7,117,110,105,49,69,50,54,7,117,110,105,49,69,50,55,7,117,110,105,49,69,50,56,7,117,110, +105,49,69,50,57,7,117,110,105,49,69,50,65,7,117,110,105,49,69,50,66,7,117,110,105,49,69,50,67,7,117,110,105,49,69,50,68,7,117,110,105,49,69,51,48,7,117,110,105,49,69,51,49,7,117,110,105,49,69,51,50,7,117,110,105,49,69,51,51,7,117,110,105,49,69,51,52, +7,117,110,105,49,69,51,53,7,117,110,105,49,69,51,54,7,117,110,105,49,69,51,55,7,117,110,105,49,69,51,56,7,117,110,105,49,69,51,57,7,117,110,105,49,69,51,65,7,117,110,105,49,69,51,66,7,117,110,105,49,69,51,67,7,117,110,105,49,69,51,68,7,117,110,105,49, +69,51,69,7,117,110,105,49,69,51,70,7,117,110,105,49,69,52,48,7,117,110,105,49,69,52,49,7,117,110,105,49,69,52,50,7,117,110,105,49,69,52,51,7,117,110,105,49,69,52,52,7,117,110,105,49,69,52,53,7,117,110,105,49,69,52,54,7,117,110,105,49,69,52,55,7,117,110, +105,49,69,52,56,7,117,110,105,49,69,52,57,7,117,110,105,49,69,52,65,7,117,110,105,49,69,52,66,7,117,110,105,49,69,52,67,7,117,110,105,49,69,52,68,7,117,110,105,49,69,53,52,7,117,110,105,49,69,53,53,7,117,110,105,49,69,53,54,7,117,110,105,49,69,53,55, +7,117,110,105,49,69,53,56,7,117,110,105,49,69,53,57,7,117,110,105,49,69,53,65,7,117,110,105,49,69,53,66,7,117,110,105,49,69,53,67,7,117,110,105,49,69,53,68,7,117,110,105,49,69,53,69,7,117,110,105,49,69,53,70,7,117,110,105,49,69,54,48,7,117,110,105,49, +69,54,49,7,117,110,105,49,69,54,50,7,117,110,105,49,69,54,51,7,117,110,105,49,69,54,56,7,117,110,105,49,69,54,57,7,117,110,105,49,69,54,65,7,117,110,105,49,69,54,66,7,117,110,105,49,69,54,67,7,117,110,105,49,69,54,68,7,117,110,105,49,69,54,69,7,117,110, +105,49,69,54,70,7,117,110,105,49,69,55,48,7,117,110,105,49,69,55,49,7,117,110,105,49,69,55,50,7,117,110,105,49,69,55,51,7,117,110,105,49,69,55,52,7,117,110,105,49,69,55,53,7,117,110,105,49,69,55,54,7,117,110,105,49,69,55,55,7,117,110,105,49,69,55,56, +7,117,110,105,49,69,55,57,7,117,110,105,49,69,55,67,7,117,110,105,49,69,55,68,7,117,110,105,49,69,55,69,7,117,110,105,49,69,55,70,6,87,103,114,97,118,101,6,119,103,114,97,118,101,6,87,97,99,117,116,101,6,119,97,99,117,116,101,9,87,100,105,101,114,101, +115,105,115,9,119,100,105,101,114,101,115,105,115,7,117,110,105,49,69,56,54,7,117,110,105,49,69,56,55,7,117,110,105,49,69,56,56,7,117,110,105,49,69,56,57,7,117,110,105,49,69,56,65,7,117,110,105,49,69,56,66,7,117,110,105,49,69,56,67,7,117,110,105,49,69, +56,68,7,117,110,105,49,69,56,69,7,117,110,105,49,69,56,70,7,117,110,105,49,69,57,48,7,117,110,105,49,69,57,49,7,117,110,105,49,69,57,50,7,117,110,105,49,69,57,51,7,117,110,105,49,69,57,52,7,117,110,105,49,69,57,53,7,117,110,105,49,69,57,54,7,117,110, +105,49,69,57,55,7,117,110,105,49,69,57,56,7,117,110,105,49,69,57,57,7,117,110,105,49,69,57,66,7,117,110,105,49,69,57,70,7,117,110,105,49,69,65,48,7,117,110,105,49,69,65,49,7,117,110,105,49,69,65,67,7,117,110,105,49,69,65,68,7,117,110,105,49,69,66,48, +7,117,110,105,49,69,66,49,7,117,110,105,49,69,66,54,7,117,110,105,49,69,66,55,7,117,110,105,49,69,66,56,7,117,110,105,49,69,66,57,7,117,110,105,49,69,66,67,7,117,110,105,49,69,66,68,7,117,110,105,49,69,67,54,7,117,110,105,49,69,67,55,7,117,110,105,49, +69,67,65,7,117,110,105,49,69,67,66,7,117,110,105,49,69,67,67,7,117,110,105,49,69,67,68,7,117,110,105,49,69,68,56,7,117,110,105,49,69,68,57,7,117,110,105,49,69,68,65,7,117,110,105,49,69,68,66,7,117,110,105,49,69,68,67,7,117,110,105,49,69,68,68,7,117,110, +105,49,69,69,48,7,117,110,105,49,69,69,49,7,117,110,105,49,69,69,50,7,117,110,105,49,69,69,51,7,117,110,105,49,69,69,52,7,117,110,105,49,69,69,53,7,117,110,105,49,69,69,56,7,117,110,105,49,69,69,57,7,117,110,105,49,69,69,65,7,117,110,105,49,69,69,66, +7,117,110,105,49,69,69,69,7,117,110,105,49,69,69,70,7,117,110,105,49,69,70,48,7,117,110,105,49,69,70,49,6,89,103,114,97,118,101,6,121,103,114,97,118,101,7,117,110,105,49,69,70,52,7,117,110,105,49,69,70,53,7,117,110,105,49,69,70,56,7,117,110,105,49,69, +70,57,7,117,110,105,49,70,48,48,7,117,110,105,49,70,48,49,7,117,110,105,49,70,48,50,7,117,110,105,49,70,48,51,7,117,110,105,49,70,48,52,7,117,110,105,49,70,48,53,7,117,110,105,49,70,48,54,7,117,110,105,49,70,48,55,7,117,110,105,49,70,48,56,7,117,110, +105,49,70,48,57,7,117,110,105,49,70,48,65,7,117,110,105,49,70,48,66,7,117,110,105,49,70,48,67,7,117,110,105,49,70,48,68,7,117,110,105,49,70,48,69,7,117,110,105,49,70,48,70,7,117,110,105,49,70,49,48,7,117,110,105,49,70,49,49,7,117,110,105,49,70,49,50, +7,117,110,105,49,70,49,51,7,117,110,105,49,70,49,52,7,117,110,105,49,70,49,53,7,117,110,105,49,70,49,56,7,117,110,105,49,70,49,57,7,117,110,105,49,70,49,65,7,117,110,105,49,70,49,66,7,117,110,105,49,70,49,67,7,117,110,105,49,70,49,68,7,117,110,105,49, +70,50,48,7,117,110,105,49,70,50,49,7,117,110,105,49,70,50,50,7,117,110,105,49,70,50,51,7,117,110,105,49,70,50,52,7,117,110,105,49,70,50,53,7,117,110,105,49,70,50,54,7,117,110,105,49,70,50,55,7,117,110,105,49,70,50,56,7,117,110,105,49,70,50,57,7,117,110, +105,49,70,50,65,7,117,110,105,49,70,50,66,7,117,110,105,49,70,50,67,7,117,110,105,49,70,50,68,7,117,110,105,49,70,50,69,7,117,110,105,49,70,50,70,7,117,110,105,49,70,51,48,7,117,110,105,49,70,51,49,7,117,110,105,49,70,51,50,7,117,110,105,49,70,51,51, +7,117,110,105,49,70,51,52,7,117,110,105,49,70,51,53,7,117,110,105,49,70,51,54,7,117,110,105,49,70,51,55,7,117,110,105,49,70,51,56,7,117,110,105,49,70,51,57,7,117,110,105,49,70,51,65,7,117,110,105,49,70,51,66,7,117,110,105,49,70,51,67,7,117,110,105,49, +70,51,68,7,117,110,105,49,70,51,69,7,117,110,105,49,70,51,70,7,117,110,105,49,70,52,48,7,117,110,105,49,70,52,49,7,117,110,105,49,70,52,50,7,117,110,105,49,70,52,51,7,117,110,105,49,70,52,52,7,117,110,105,49,70,52,53,7,117,110,105,49,70,52,56,7,117,110, +105,49,70,52,57,7,117,110,105,49,70,52,65,7,117,110,105,49,70,52,66,7,117,110,105,49,70,52,67,7,117,110,105,49,70,52,68,7,117,110,105,49,70,53,48,7,117,110,105,49,70,53,49,7,117,110,105,49,70,53,50,7,117,110,105,49,70,53,51,7,117,110,105,49,70,53,52, +7,117,110,105,49,70,53,53,7,117,110,105,49,70,53,54,7,117,110,105,49,70,53,55,7,117,110,105,49,70,53,57,7,117,110,105,49,70,53,66,7,117,110,105,49,70,53,68,7,117,110,105,49,70,53,70,7,117,110,105,49,70,54,48,7,117,110,105,49,70,54,49,7,117,110,105,49, +70,54,50,7,117,110,105,49,70,54,51,7,117,110,105,49,70,54,52,7,117,110,105,49,70,54,53,7,117,110,105,49,70,54,54,7,117,110,105,49,70,54,55,7,117,110,105,49,70,54,56,7,117,110,105,49,70,54,57,7,117,110,105,49,70,54,65,7,117,110,105,49,70,54,66,7,117,110, +105,49,70,54,67,7,117,110,105,49,70,54,68,7,117,110,105,49,70,54,69,7,117,110,105,49,70,54,70,7,117,110,105,49,70,55,48,7,117,110,105,49,70,55,49,7,117,110,105,49,70,55,50,7,117,110,105,49,70,55,51,7,117,110,105,49,70,55,52,7,117,110,105,49,70,55,53, +7,117,110,105,49,70,55,54,7,117,110,105,49,70,55,55,7,117,110,105,49,70,55,56,7,117,110,105,49,70,55,57,7,117,110,105,49,70,55,65,7,117,110,105,49,70,55,66,7,117,110,105,49,70,55,67,7,117,110,105,49,70,55,68,7,117,110,105,49,70,56,48,7,117,110,105,49, +70,56,49,7,117,110,105,49,70,56,50,7,117,110,105,49,70,56,51,7,117,110,105,49,70,56,52,7,117,110,105,49,70,56,53,7,117,110,105,49,70,56,54,7,117,110,105,49,70,56,55,7,117,110,105,49,70,56,56,7,117,110,105,49,70,56,57,7,117,110,105,49,70,56,65,7,117,110, +105,49,70,56,66,7,117,110,105,49,70,56,67,7,117,110,105,49,70,56,68,7,117,110,105,49,70,56,69,7,117,110,105,49,70,56,70,7,117,110,105,49,70,57,48,7,117,110,105,49,70,57,49,7,117,110,105,49,70,57,50,7,117,110,105,49,70,57,51,7,117,110,105,49,70,57,52, +7,117,110,105,49,70,57,53,7,117,110,105,49,70,57,54,7,117,110,105,49,70,57,55,7,117,110,105,49,70,57,56,7,117,110,105,49,70,57,57,7,117,110,105,49,70,57,65,7,117,110,105,49,70,57,66,7,117,110,105,49,70,57,67,7,117,110,105,49,70,57,68,7,117,110,105,49, +70,57,69,7,117,110,105,49,70,57,70,7,117,110,105,49,70,65,48,7,117,110,105,49,70,65,49,7,117,110,105,49,70,65,50,7,117,110,105,49,70,65,51,7,117,110,105,49,70,65,52,7,117,110,105,49,70,65,53,7,117,110,105,49,70,65,54,7,117,110,105,49,70,65,55,7,117,110, +105,49,70,65,56,7,117,110,105,49,70,65,57,7,117,110,105,49,70,65,65,7,117,110,105,49,70,65,66,7,117,110,105,49,70,65,67,7,117,110,105,49,70,65,68,7,117,110,105,49,70,65,69,7,117,110,105,49,70,65,70,7,117,110,105,49,70,66,48,7,117,110,105,49,70,66,49, +7,117,110,105,49,70,66,50,7,117,110,105,49,70,66,51,7,117,110,105,49,70,66,52,7,117,110,105,49,70,66,54,7,117,110,105,49,70,66,55,7,117,110,105,49,70,66,56,7,117,110,105,49,70,66,57,7,117,110,105,49,70,66,65,7,117,110,105,49,70,66,66,7,117,110,105,49, +70,66,67,7,117,110,105,49,70,66,68,7,117,110,105,49,70,66,69,7,117,110,105,49,70,66,70,7,117,110,105,49,70,67,48,7,117,110,105,49,70,67,49,7,117,110,105,49,70,67,50,7,117,110,105,49,70,67,51,7,117,110,105,49,70,67,52,7,117,110,105,49,70,67,54,7,117,110, +105,49,70,67,55,7,117,110,105,49,70,67,56,7,117,110,105,49,70,67,57,7,117,110,105,49,70,67,65,7,117,110,105,49,70,67,66,7,117,110,105,49,70,67,67,7,117,110,105,49,70,67,68,7,117,110,105,49,70,67,69,7,117,110,105,49,70,67,70,7,117,110,105,49,70,68,48, +7,117,110,105,49,70,68,49,7,117,110,105,49,70,68,50,7,117,110,105,49,70,68,51,7,117,110,105,49,70,68,54,7,117,110,105,49,70,68,55,7,117,110,105,49,70,68,56,7,117,110,105,49,70,68,57,7,117,110,105,49,70,68,65,7,117,110,105,49,70,68,66,7,117,110,105,49, +70,68,68,7,117,110,105,49,70,68,69,7,117,110,105,49,70,68,70,7,117,110,105,49,70,69,48,7,117,110,105,49,70,69,49,7,117,110,105,49,70,69,50,7,117,110,105,49,70,69,51,7,117,110,105,49,70,69,52,7,117,110,105,49,70,69,53,7,117,110,105,49,70,69,54,7,117,110, +105,49,70,69,55,7,117,110,105,49,70,69,56,7,117,110,105,49,70,69,57,7,117,110,105,49,70,69,65,7,117,110,105,49,70,69,66,7,117,110,105,49,70,69,67,7,117,110,105,49,70,69,68,7,117,110,105,49,70,69,69,7,117,110,105,49,70,69,70,7,117,110,105,49,70,70,50, +7,117,110,105,49,70,70,51,7,117,110,105,49,70,70,52,7,117,110,105,49,70,70,54,7,117,110,105,49,70,70,55,7,117,110,105,49,70,70,56,7,117,110,105,49,70,70,57,7,117,110,105,49,70,70,65,7,117,110,105,49,70,70,66,7,117,110,105,49,70,70,67,7,117,110,105,49, +70,70,68,7,117,110,105,49,70,70,69,7,117,110,105,50,48,48,48,7,117,110,105,50,48,48,49,7,117,110,105,50,48,48,50,7,117,110,105,50,48,48,51,7,117,110,105,50,48,48,52,7,117,110,105,50,48,48,53,7,117,110,105,50,48,48,54,7,117,110,105,50,48,48,55,7,117,110, +105,50,48,48,56,7,117,110,105,50,48,48,57,7,117,110,105,50,48,48,65,7,117,110,105,50,48,49,48,7,117,110,105,50,48,49,49,10,102,105,103,117,114,101,100,97,115,104,7,117,110,105,50,48,49,53,7,117,110,105,50,48,49,54,13,117,110,100,101,114,115,99,111,114, +101,100,98,108,13,113,117,111,116,101,114,101,118,101,114,115,101,100,7,117,110,105,50,48,49,70,7,117,110,105,50,48,50,51,7,117,110,105,50,48,50,70,7,117,110,105,50,48,51,49,6,109,105,110,117,116,101,6,115,101,99,111,110,100,7,117,110,105,50,48,51,52, +7,117,110,105,50,48,51,53,7,117,110,105,50,48,51,54,7,117,110,105,50,48,51,55,9,101,120,99,108,97,109,100,98,108,7,117,110,105,50,48,51,68,7,117,110,105,50,48,51,69,7,117,110,105,50,48,51,70,7,117,110,105,50,48,52,53,7,117,110,105,50,48,52,54,7,117,110, +105,50,48,52,55,7,117,110,105,50,48,52,56,7,117,110,105,50,48,52,57,7,117,110,105,50,48,52,66,7,117,110,105,50,48,53,70,7,117,110,105,50,48,55,48,7,117,110,105,50,48,55,49,7,117,110,105,50,48,55,52,7,117,110,105,50,48,55,53,7,117,110,105,50,48,55,54, +7,117,110,105,50,48,55,55,7,117,110,105,50,48,55,56,7,117,110,105,50,48,55,57,7,117,110,105,50,48,55,65,7,117,110,105,50,48,55,66,7,117,110,105,50,48,55,67,7,117,110,105,50,48,55,68,7,117,110,105,50,48,55,69,7,117,110,105,50,48,55,70,7,117,110,105,50, +48,56,48,7,117,110,105,50,48,56,49,7,117,110,105,50,48,56,50,7,117,110,105,50,48,56,51,7,117,110,105,50,48,56,52,7,117,110,105,50,48,56,53,7,117,110,105,50,48,56,54,7,117,110,105,50,48,56,55,7,117,110,105,50,48,56,56,7,117,110,105,50,48,56,57,7,117,110, +105,50,48,56,65,7,117,110,105,50,48,56,66,7,117,110,105,50,48,56,67,7,117,110,105,50,48,56,68,7,117,110,105,50,48,56,69,7,117,110,105,50,48,57,48,7,117,110,105,50,48,57,49,7,117,110,105,50,48,57,50,7,117,110,105,50,48,57,51,7,117,110,105,50,48,57,52, +7,117,110,105,50,48,57,53,7,117,110,105,50,48,57,54,7,117,110,105,50,48,57,55,7,117,110,105,50,48,57,56,7,117,110,105,50,48,57,57,7,117,110,105,50,48,57,65,7,117,110,105,50,48,57,66,7,117,110,105,50,48,57,67,7,117,110,105,50,48,65,48,13,99,111,108,111, +110,109,111,110,101,116,97,114,121,7,117,110,105,50,48,65,50,4,108,105,114,97,7,117,110,105,50,48,65,53,7,117,110,105,50,48,65,54,6,112,101,115,101,116,97,7,117,110,105,50,48,65,56,7,117,110,105,50,48,65,57,7,117,110,105,50,48,65,65,4,100,111,110,103, +4,69,117,114,111,7,117,110,105,50,48,65,68,7,117,110,105,50,48,65,69,7,117,110,105,50,48,65,70,7,117,110,105,50,48,66,48,7,117,110,105,50,48,66,49,7,117,110,105,50,48,66,50,7,117,110,105,50,48,66,51,7,117,110,105,50,48,66,52,7,117,110,105,50,48,66,53, +7,117,110,105,50,48,66,56,7,117,110,105,50,48,66,57,7,117,110,105,50,48,66,65,7,117,110,105,50,48,66,68,7,117,110,105,50,49,48,50,7,117,110,105,50,49,48,53,7,117,110,105,50,49,48,68,7,117,110,105,50,49,48,69,7,117,110,105,50,49,48,70,7,117,110,105,50, +49,49,53,7,117,110,105,50,49,49,54,7,117,110,105,50,49,49,55,7,117,110,105,50,49,49,57,7,117,110,105,50,49,49,65,7,117,110,105,50,49,49,68,7,117,110,105,50,49,50,52,7,117,110,105,50,49,50,54,7,117,110,105,50,49,50,65,7,117,110,105,50,49,50,66,9,101,115, +116,105,109,97,116,101,100,7,117,110,105,50,49,52,56,7,117,110,105,50,49,53,48,7,117,110,105,50,49,53,49,8,111,110,101,116,104,105,114,100,9,116,119,111,116,104,105,114,100,115,7,117,110,105,50,49,53,53,7,117,110,105,50,49,53,54,7,117,110,105,50,49,53, +55,7,117,110,105,50,49,53,56,7,117,110,105,50,49,53,57,7,117,110,105,50,49,53,65,9,111,110,101,101,105,103,104,116,104,12,116,104,114,101,101,101,105,103,104,116,104,115,11,102,105,118,101,101,105,103,104,116,104,115,12,115,101,118,101,110,101,105,103, +104,116,104,115,7,117,110,105,50,49,53,70,7,117,110,105,50,49,56,57,9,97,114,114,111,119,108,101,102,116,7,97,114,114,111,119,117,112,10,97,114,114,111,119,114,105,103,104,116,9,97,114,114,111,119,100,111,119,110,9,97,114,114,111,119,98,111,116,104,9, +97,114,114,111,119,117,112,100,110,7,117,110,105,50,49,57,54,7,117,110,105,50,49,57,55,7,117,110,105,50,49,57,56,7,117,110,105,50,49,57,57,7,117,110,105,50,49,57,65,7,117,110,105,50,49,57,66,7,117,110,105,50,49,57,67,7,117,110,105,50,49,57,68,7,117,110, +105,50,49,57,69,7,117,110,105,50,49,57,70,7,117,110,105,50,49,65,48,7,117,110,105,50,49,65,49,7,117,110,105,50,49,65,50,7,117,110,105,50,49,65,51,7,117,110,105,50,49,65,52,7,117,110,105,50,49,65,53,7,117,110,105,50,49,65,54,7,117,110,105,50,49,65,55, +12,97,114,114,111,119,117,112,100,110,98,115,101,7,117,110,105,50,49,65,57,7,117,110,105,50,49,65,65,7,117,110,105,50,49,65,66,7,117,110,105,50,49,65,67,7,117,110,105,50,49,65,68,7,117,110,105,50,49,65,69,7,117,110,105,50,49,65,70,7,117,110,105,50,49, +66,48,7,117,110,105,50,49,66,49,7,117,110,105,50,49,66,50,7,117,110,105,50,49,66,51,7,117,110,105,50,49,66,52,14,99,97,114,114,105,97,103,101,114,101,116,117,114,110,7,117,110,105,50,49,66,54,7,117,110,105,50,49,66,55,7,117,110,105,50,49,66,56,7,117, +110,105,50,49,66,57,7,117,110,105,50,49,66,65,7,117,110,105,50,49,66,66,7,117,110,105,50,49,66,67,7,117,110,105,50,49,66,68,7,117,110,105,50,49,66,69,7,117,110,105,50,49,66,70,7,117,110,105,50,49,67,48,7,117,110,105,50,49,67,49,7,117,110,105,50,49,67, +50,7,117,110,105,50,49,67,51,7,117,110,105,50,49,67,52,7,117,110,105,50,49,67,53,7,117,110,105,50,49,67,54,7,117,110,105,50,49,67,55,7,117,110,105,50,49,67,56,7,117,110,105,50,49,67,57,7,117,110,105,50,49,67,65,7,117,110,105,50,49,67,66,7,117,110,105, +50,49,67,67,7,117,110,105,50,49,67,68,7,117,110,105,50,49,67,69,7,117,110,105,50,49,67,70,12,97,114,114,111,119,100,98,108,108,101,102,116,10,97,114,114,111,119,100,98,108,117,112,13,97,114,114,111,119,100,98,108,114,105,103,104,116,12,97,114,114,111, +119,100,98,108,100,111,119,110,12,97,114,114,111,119,100,98,108,98,111,116,104,7,117,110,105,50,49,68,53,7,117,110,105,50,49,68,54,7,117,110,105,50,49,68,55,7,117,110,105,50,49,68,56,7,117,110,105,50,49,68,57,7,117,110,105,50,49,68,65,7,117,110,105,50, +49,68,66,7,117,110,105,50,49,68,67,7,117,110,105,50,49,68,68,7,117,110,105,50,49,68,69,7,117,110,105,50,49,68,70,7,117,110,105,50,49,69,48,7,117,110,105,50,49,69,49,7,117,110,105,50,49,69,50,7,117,110,105,50,49,69,51,7,117,110,105,50,49,69,52,7,117,110, +105,50,49,69,53,7,117,110,105,50,49,69,54,7,117,110,105,50,49,69,55,7,117,110,105,50,49,69,56,7,117,110,105,50,49,69,57,7,117,110,105,50,49,69,65,7,117,110,105,50,49,69,66,7,117,110,105,50,49,69,67,7,117,110,105,50,49,69,68,7,117,110,105,50,49,69,69, +7,117,110,105,50,49,69,70,7,117,110,105,50,49,70,48,7,117,110,105,50,49,70,49,7,117,110,105,50,49,70,50,7,117,110,105,50,49,70,51,7,117,110,105,50,49,70,52,7,117,110,105,50,49,70,53,7,117,110,105,50,49,70,54,7,117,110,105,50,49,70,55,7,117,110,105,50, +49,70,56,7,117,110,105,50,49,70,57,7,117,110,105,50,49,70,65,7,117,110,105,50,49,70,66,7,117,110,105,50,49,70,67,7,117,110,105,50,49,70,68,7,117,110,105,50,49,70,69,7,117,110,105,50,49,70,70,9,117,110,105,118,101,114,115,97,108,7,117,110,105,50,50,48, +49,11,101,120,105,115,116,101,110,116,105,97,108,7,117,110,105,50,50,48,52,8,101,109,112,116,121,115,101,116,8,103,114,97,100,105,101,110,116,7,101,108,101,109,101,110,116,10,110,111,116,101,108,101,109,101,110,116,7,117,110,105,50,50,48,65,8,115,117, +99,104,116,104,97,116,7,117,110,105,50,50,48,67,7,117,110,105,50,50,48,68,7,117,110,105,50,50,48,69,7,117,110,105,50,50,49,48,7,117,110,105,50,50,49,51,7,117,110,105,50,50,49,53,12,97,115,116,101,114,105,115,107,109,97,116,104,7,117,110,105,50,50,49, +56,7,117,110,105,50,50,49,57,7,117,110,105,50,50,49,66,7,117,110,105,50,50,49,67,12,112,114,111,112,111,114,116,105,111,110,97,108,10,111,114,116,104,111,103,111,110,97,108,5,97,110,103,108,101,7,117,110,105,50,50,50,51,10,108,111,103,105,99,97,108,97, +110,100,9,108,111,103,105,99,97,108,111,114,12,105,110,116,101,114,115,101,99,116,105,111,110,5,117,110,105,111,110,7,117,110,105,50,50,50,67,7,117,110,105,50,50,50,68,9,116,104,101,114,101,102,111,114,101,7,117,110,105,50,50,51,53,7,117,110,105,50,50, +51,54,7,117,110,105,50,50,51,55,7,117,110,105,50,50,51,56,7,117,110,105,50,50,51,57,7,117,110,105,50,50,51,65,7,117,110,105,50,50,51,66,7,115,105,109,105,108,97,114,7,117,110,105,50,50,51,68,7,117,110,105,50,50,52,49,7,117,110,105,50,50,52,50,7,117,110, +105,50,50,52,51,7,117,110,105,50,50,52,52,9,99,111,110,103,114,117,101,110,116,7,117,110,105,50,50,52,54,7,117,110,105,50,50,52,55,7,117,110,105,50,50,52,57,7,117,110,105,50,50,52,65,7,117,110,105,50,50,52,66,7,117,110,105,50,50,52,67,7,117,110,105,50, +50,52,68,7,117,110,105,50,50,52,69,7,117,110,105,50,50,52,70,7,117,110,105,50,50,53,48,7,117,110,105,50,50,53,49,7,117,110,105,50,50,53,50,7,117,110,105,50,50,53,51,7,117,110,105,50,50,53,52,7,117,110,105,50,50,53,53,7,117,110,105,50,50,53,54,7,117,110, +105,50,50,53,55,7,117,110,105,50,50,53,56,7,117,110,105,50,50,53,57,7,117,110,105,50,50,53,65,7,117,110,105,50,50,53,66,7,117,110,105,50,50,53,67,7,117,110,105,50,50,53,68,7,117,110,105,50,50,53,69,7,117,110,105,50,50,53,70,11,101,113,117,105,118,97, +108,101,110,99,101,7,117,110,105,50,50,54,50,7,117,110,105,50,50,54,51,7,117,110,105,50,50,54,54,7,117,110,105,50,50,54,55,7,117,110,105,50,50,54,56,7,117,110,105,50,50,54,57,7,117,110,105,50,50,54,68,7,117,110,105,50,50,54,69,7,117,110,105,50,50,54, +70,7,117,110,105,50,50,55,48,7,117,110,105,50,50,55,49,7,117,110,105,50,50,55,50,7,117,110,105,50,50,55,51,7,117,110,105,50,50,55,52,7,117,110,105,50,50,55,53,7,117,110,105,50,50,55,54,7,117,110,105,50,50,55,55,7,117,110,105,50,50,55,56,7,117,110,105, +50,50,55,57,7,117,110,105,50,50,55,65,7,117,110,105,50,50,55,66,7,117,110,105,50,50,55,67,7,117,110,105,50,50,55,68,7,117,110,105,50,50,55,69,7,117,110,105,50,50,55,70,7,117,110,105,50,50,56,48,7,117,110,105,50,50,56,49,12,112,114,111,112,101,114,115, +117,98,115,101,116,14,112,114,111,112,101,114,115,117,112,101,114,115,101,116,9,110,111,116,115,117,98,115,101,116,7,117,110,105,50,50,56,53,12,114,101,102,108,101,120,115,117,98,115,101,116,14,114,101,102,108,101,120,115,117,112,101,114,115,101,116, +7,117,110,105,50,50,56,56,7,117,110,105,50,50,56,57,7,117,110,105,50,50,56,65,7,117,110,105,50,50,56,66,7,117,110,105,50,50,56,68,7,117,110,105,50,50,56,69,7,117,110,105,50,50,56,70,7,117,110,105,50,50,57,48,7,117,110,105,50,50,57,49,7,117,110,105,50, +50,57,50,7,117,110,105,50,50,57,51,7,117,110,105,50,50,57,52,10,99,105,114,99,108,101,112,108,117,115,7,117,110,105,50,50,57,54,14,99,105,114,99,108,101,109,117,108,116,105,112,108,121,7,117,110,105,50,50,57,56,7,117,110,105,50,50,57,57,7,117,110,105, +50,50,57,65,7,117,110,105,50,50,57,66,7,117,110,105,50,50,57,67,7,117,110,105,50,50,57,68,7,117,110,105,50,50,57,69,7,117,110,105,50,50,57,70,7,117,110,105,50,50,65,48,7,117,110,105,50,50,65,49,7,117,110,105,50,50,65,50,7,117,110,105,50,50,65,51,7,117, +110,105,50,50,65,52,13,112,101,114,112,101,110,100,105,99,117,108,97,114,7,117,110,105,50,50,66,50,7,117,110,105,50,50,66,51,7,117,110,105,50,50,66,52,7,117,110,105,50,50,66,53,7,117,110,105,50,50,66,56,7,117,110,105,50,50,67,50,7,117,110,105,50,50,67, +51,7,117,110,105,50,50,67,52,7,100,111,116,109,97,116,104,7,117,110,105,50,50,67,54,7,117,110,105,50,50,67,68,7,117,110,105,50,50,67,69,7,117,110,105,50,50,67,70,7,117,110,105,50,50,68,48,7,117,110,105,50,50,68,49,7,117,110,105,50,50,68,65,7,117,110, +105,50,50,68,66,7,117,110,105,50,50,68,67,7,117,110,105,50,50,68,68,7,117,110,105,50,50,68,69,7,117,110,105,50,50,68,70,7,117,110,105,50,50,69,48,7,117,110,105,50,50,69,49,7,117,110,105,50,50,69,50,7,117,110,105,50,50,69,51,7,117,110,105,50,50,69,52, +7,117,110,105,50,50,69,53,7,117,110,105,50,50,69,54,7,117,110,105,50,50,69,55,7,117,110,105,50,50,69,56,7,117,110,105,50,50,69,57,7,117,110,105,50,50,69,70,7,117,110,105,50,51,48,48,7,117,110,105,50,51,48,49,5,104,111,117,115,101,7,117,110,105,50,51, +48,51,7,117,110,105,50,51,48,52,7,117,110,105,50,51,48,53,7,117,110,105,50,51,48,54,7,117,110,105,50,51,48,56,7,117,110,105,50,51,48,57,7,117,110,105,50,51,48,65,7,117,110,105,50,51,48,66,7,117,110,105,50,51,48,67,7,117,110,105,50,51,48,68,7,117,110, +105,50,51,48,69,7,117,110,105,50,51,48,70,13,114,101,118,108,111,103,105,99,97,108,110,111,116,7,117,110,105,50,51,49,49,7,117,110,105,50,51,49,50,7,117,110,105,50,51,49,51,7,117,110,105,50,51,49,52,7,117,110,105,50,51,49,53,7,117,110,105,50,51,49,56, +7,117,110,105,50,51,49,57,7,117,110,105,50,51,49,67,7,117,110,105,50,51,49,68,7,117,110,105,50,51,49,69,7,117,110,105,50,51,49,70,10,105,110,116,101,103,114,97,108,116,112,10,105,110,116,101,103,114,97,108,98,116,7,117,110,105,50,51,50,53,7,117,110,105, +50,51,50,54,7,117,110,105,50,51,50,55,7,117,110,105,50,51,50,56,7,117,110,105,50,51,50,66,7,117,110,105,50,51,51,53,7,117,110,105,50,51,51,54,7,117,110,105,50,51,51,55,7,117,110,105,50,51,51,56,7,117,110,105,50,51,51,57,7,117,110,105,50,51,51,65,7,117, +110,105,50,51,51,66,7,117,110,105,50,51,51,67,7,117,110,105,50,51,51,68,7,117,110,105,50,51,51,69,7,117,110,105,50,51,51,70,7,117,110,105,50,51,52,48,7,117,110,105,50,51,52,49,7,117,110,105,50,51,52,50,7,117,110,105,50,51,52,51,7,117,110,105,50,51,52, +52,7,117,110,105,50,51,52,53,7,117,110,105,50,51,52,54,7,117,110,105,50,51,52,55,7,117,110,105,50,51,52,56,7,117,110,105,50,51,52,57,7,117,110,105,50,51,52,65,7,117,110,105,50,51,52,66,7,117,110,105,50,51,52,67,7,117,110,105,50,51,52,68,7,117,110,105, +50,51,52,69,7,117,110,105,50,51,52,70,7,117,110,105,50,51,53,48,7,117,110,105,50,51,53,49,7,117,110,105,50,51,53,50,7,117,110,105,50,51,53,51,7,117,110,105,50,51,53,52,7,117,110,105,50,51,53,53,7,117,110,105,50,51,53,54,7,117,110,105,50,51,53,55,7,117, +110,105,50,51,53,56,7,117,110,105,50,51,53,57,7,117,110,105,50,51,53,65,7,117,110,105,50,51,53,66,7,117,110,105,50,51,53,67,7,117,110,105,50,51,53,68,7,117,110,105,50,51,53,69,7,117,110,105,50,51,53,70,7,117,110,105,50,51,54,48,7,117,110,105,50,51,54, +49,7,117,110,105,50,51,54,50,7,117,110,105,50,51,54,51,7,117,110,105,50,51,54,52,7,117,110,105,50,51,54,53,7,117,110,105,50,51,54,54,7,117,110,105,50,51,54,55,7,117,110,105,50,51,54,56,7,117,110,105,50,51,54,57,7,117,110,105,50,51,54,65,7,117,110,105, +50,51,54,66,7,117,110,105,50,51,54,67,7,117,110,105,50,51,54,68,7,117,110,105,50,51,54,69,7,117,110,105,50,51,54,70,7,117,110,105,50,51,55,48,7,117,110,105,50,51,55,49,7,117,110,105,50,51,55,50,7,117,110,105,50,51,55,51,7,117,110,105,50,51,55,52,7,117, +110,105,50,51,55,53,7,117,110,105,50,51,55,54,7,117,110,105,50,51,55,55,7,117,110,105,50,51,55,56,7,117,110,105,50,51,55,57,7,117,110,105,50,51,55,65,7,117,110,105,50,51,55,68,7,117,110,105,50,51,56,48,7,117,110,105,50,51,56,49,7,117,110,105,50,51,56, +50,7,117,110,105,50,51,56,51,7,117,110,105,50,51,56,56,7,117,110,105,50,51,56,57,7,117,110,105,50,51,56,65,7,117,110,105,50,51,56,66,7,117,110,105,50,51,57,53,7,117,110,105,50,51,57,66,7,117,110,105,50,51,57,67,7,117,110,105,50,51,57,68,7,117,110,105, +50,51,57,69,7,117,110,105,50,51,57,70,7,117,110,105,50,51,65,48,7,117,110,105,50,51,65,49,7,117,110,105,50,51,65,50,7,117,110,105,50,51,65,51,7,117,110,105,50,51,65,52,7,117,110,105,50,51,65,53,7,117,110,105,50,51,65,54,7,117,110,105,50,51,65,55,7,117, +110,105,50,51,65,56,7,117,110,105,50,51,65,57,7,117,110,105,50,51,65,65,7,117,110,105,50,51,65,66,7,117,110,105,50,51,65,67,7,117,110,105,50,51,65,68,7,117,110,105,50,51,65,69,7,117,110,105,50,51,67,69,7,117,110,105,50,51,67,70,7,117,110,105,50,52,50, +51,8,83,70,49,48,48,48,48,48,7,117,110,105,50,53,48,49,8,83,70,49,49,48,48,48,48,7,117,110,105,50,53,48,51,7,117,110,105,50,53,48,52,7,117,110,105,50,53,48,53,7,117,110,105,50,53,48,54,7,117,110,105,50,53,48,55,7,117,110,105,50,53,48,56,7,117,110,105, +50,53,48,57,7,117,110,105,50,53,48,65,7,117,110,105,50,53,48,66,8,83,70,48,49,48,48,48,48,7,117,110,105,50,53,48,68,7,117,110,105,50,53,48,69,7,117,110,105,50,53,48,70,8,83,70,48,51,48,48,48,48,7,117,110,105,50,53,49,49,7,117,110,105,50,53,49,50,7,117, +110,105,50,53,49,51,8,83,70,48,50,48,48,48,48,7,117,110,105,50,53,49,53,7,117,110,105,50,53,49,54,7,117,110,105,50,53,49,55,8,83,70,48,52,48,48,48,48,7,117,110,105,50,53,49,57,7,117,110,105,50,53,49,65,7,117,110,105,50,53,49,66,8,83,70,48,56,48,48,48, +48,7,117,110,105,50,53,49,68,7,117,110,105,50,53,49,69,7,117,110,105,50,53,49,70,7,117,110,105,50,53,50,48,7,117,110,105,50,53,50,49,7,117,110,105,50,53,50,50,7,117,110,105,50,53,50,51,8,83,70,48,57,48,48,48,48,7,117,110,105,50,53,50,53,7,117,110,105, +50,53,50,54,7,117,110,105,50,53,50,55,7,117,110,105,50,53,50,56,7,117,110,105,50,53,50,57,7,117,110,105,50,53,50,65,7,117,110,105,50,53,50,66,8,83,70,48,54,48,48,48,48,7,117,110,105,50,53,50,68,7,117,110,105,50,53,50,69,7,117,110,105,50,53,50,70,7,117, +110,105,50,53,51,48,7,117,110,105,50,53,51,49,7,117,110,105,50,53,51,50,7,117,110,105,50,53,51,51,8,83,70,48,55,48,48,48,48,7,117,110,105,50,53,51,53,7,117,110,105,50,53,51,54,7,117,110,105,50,53,51,55,7,117,110,105,50,53,51,56,7,117,110,105,50,53,51, +57,7,117,110,105,50,53,51,65,7,117,110,105,50,53,51,66,8,83,70,48,53,48,48,48,48,7,117,110,105,50,53,51,68,7,117,110,105,50,53,51,69,7,117,110,105,50,53,51,70,7,117,110,105,50,53,52,48,7,117,110,105,50,53,52,49,7,117,110,105,50,53,52,50,7,117,110,105, +50,53,52,51,7,117,110,105,50,53,52,52,7,117,110,105,50,53,52,53,7,117,110,105,50,53,52,54,7,117,110,105,50,53,52,55,7,117,110,105,50,53,52,56,7,117,110,105,50,53,52,57,7,117,110,105,50,53,52,65,7,117,110,105,50,53,52,66,7,117,110,105,50,53,52,67,7,117, +110,105,50,53,52,68,7,117,110,105,50,53,52,69,7,117,110,105,50,53,52,70,8,83,70,52,51,48,48,48,48,8,83,70,50,52,48,48,48,48,8,83,70,53,49,48,48,48,48,8,83,70,53,50,48,48,48,48,8,83,70,51,57,48,48,48,48,8,83,70,50,50,48,48,48,48,8,83,70,50,49,48,48,48, +48,8,83,70,50,53,48,48,48,48,8,83,70,53,48,48,48,48,48,8,83,70,52,57,48,48,48,48,8,83,70,51,56,48,48,48,48,8,83,70,50,56,48,48,48,48,8,83,70,50,55,48,48,48,48,8,83,70,50,54,48,48,48,48,8,83,70,51,54,48,48,48,48,8,83,70,51,55,48,48,48,48,8,83,70,52,50, +48,48,48,48,8,83,70,49,57,48,48,48,48,8,83,70,50,48,48,48,48,48,8,83,70,50,51,48,48,48,48,8,83,70,52,55,48,48,48,48,8,83,70,52,56,48,48,48,48,8,83,70,52,49,48,48,48,48,8,83,70,52,53,48,48,48,48,8,83,70,52,54,48,48,48,48,8,83,70,52,48,48,48,48,48,8,83, +70,53,52,48,48,48,48,8,83,70,53,51,48,48,48,48,8,83,70,52,52,48,48,48,48,7,117,110,105,50,53,54,68,7,117,110,105,50,53,54,69,7,117,110,105,50,53,54,70,7,117,110,105,50,53,55,48,7,117,110,105,50,53,55,49,7,117,110,105,50,53,55,50,7,117,110,105,50,53,55, +51,7,117,110,105,50,53,55,52,7,117,110,105,50,53,55,53,7,117,110,105,50,53,55,54,7,117,110,105,50,53,55,55,7,117,110,105,50,53,55,56,7,117,110,105,50,53,55,57,7,117,110,105,50,53,55,65,7,117,110,105,50,53,55,66,7,117,110,105,50,53,55,67,7,117,110,105, +50,53,55,68,7,117,110,105,50,53,55,69,7,117,110,105,50,53,55,70,7,117,112,98,108,111,99,107,7,117,110,105,50,53,56,49,7,117,110,105,50,53,56,50,7,117,110,105,50,53,56,51,7,100,110,98,108,111,99,107,7,117,110,105,50,53,56,53,7,117,110,105,50,53,56,54, +7,117,110,105,50,53,56,55,5,98,108,111,99,107,7,117,110,105,50,53,56,57,7,117,110,105,50,53,56,65,7,117,110,105,50,53,56,66,7,108,102,98,108,111,99,107,7,117,110,105,50,53,56,68,7,117,110,105,50,53,56,69,7,117,110,105,50,53,56,70,7,114,116,98,108,111, +99,107,7,108,116,115,104,97,100,101,5,115,104,97,100,101,7,100,107,115,104,97,100,101,7,117,110,105,50,53,57,52,7,117,110,105,50,53,57,53,7,117,110,105,50,53,57,54,7,117,110,105,50,53,57,55,7,117,110,105,50,53,57,56,7,117,110,105,50,53,57,57,7,117,110, +105,50,53,57,65,7,117,110,105,50,53,57,66,7,117,110,105,50,53,57,67,7,117,110,105,50,53,57,68,7,117,110,105,50,53,57,69,7,117,110,105,50,53,57,70,9,102,105,108,108,101,100,98,111,120,6,72,50,50,48,55,51,7,117,110,105,50,53,65,50,7,117,110,105,50,53,65, +51,7,117,110,105,50,53,65,52,7,117,110,105,50,53,65,53,7,117,110,105,50,53,65,54,7,117,110,105,50,53,65,55,7,117,110,105,50,53,65,56,7,117,110,105,50,53,65,57,6,72,49,56,53,52,51,6,72,49,56,53,53,49,10,102,105,108,108,101,100,114,101,99,116,7,117,110, +105,50,53,65,68,7,117,110,105,50,53,65,69,7,117,110,105,50,53,65,70,7,117,110,105,50,53,66,48,7,117,110,105,50,53,66,49,7,116,114,105,97,103,117,112,7,117,110,105,50,53,66,51,7,117,110,105,50,53,66,52,7,117,110,105,50,53,66,53,7,117,110,105,50,53,66, +54,7,117,110,105,50,53,66,55,7,117,110,105,50,53,66,56,7,117,110,105,50,53,66,57,7,116,114,105,97,103,114,116,7,117,110,105,50,53,66,66,7,116,114,105,97,103,100,110,7,117,110,105,50,53,66,68,7,117,110,105,50,53,66,69,7,117,110,105,50,53,66,70,7,117,110, +105,50,53,67,48,7,117,110,105,50,53,67,49,7,117,110,105,50,53,67,50,7,117,110,105,50,53,67,51,7,116,114,105,97,103,108,102,7,117,110,105,50,53,67,53,7,117,110,105,50,53,67,54,7,117,110,105,50,53,67,55,7,117,110,105,50,53,67,56,7,117,110,105,50,53,67, +57,6,99,105,114,99,108,101,7,117,110,105,50,53,67,67,7,117,110,105,50,53,67,68,7,117,110,105,50,53,67,69,6,72,49,56,53,51,51,7,117,110,105,50,53,68,48,7,117,110,105,50,53,68,49,7,117,110,105,50,53,68,50,7,117,110,105,50,53,68,51,7,117,110,105,50,53,68, +52,7,117,110,105,50,53,68,53,7,117,110,105,50,53,68,54,7,117,110,105,50,53,68,55,9,105,110,118,98,117,108,108,101,116,9,105,110,118,99,105,114,99,108,101,7,117,110,105,50,53,68,65,7,117,110,105,50,53,68,66,7,117,110,105,50,53,68,67,7,117,110,105,50,53, +68,68,7,117,110,105,50,53,68,69,7,117,110,105,50,53,68,70,7,117,110,105,50,53,69,48,7,117,110,105,50,53,69,49,7,117,110,105,50,53,69,50,7,117,110,105,50,53,69,51,7,117,110,105,50,53,69,52,7,117,110,105,50,53,69,53,10,111,112,101,110,98,117,108,108,101, +116,7,117,110,105,50,53,69,55,7,117,110,105,50,53,69,56,7,117,110,105,50,53,69,57,7,117,110,105,50,53,69,65,7,117,110,105,50,53,69,66,7,117,110,105,50,53,69,67,7,117,110,105,50,53,69,68,7,117,110,105,50,53,69,69,7,117,110,105,50,53,69,70,7,117,110,105, +50,53,70,48,7,117,110,105,50,53,70,49,7,117,110,105,50,53,70,50,7,117,110,105,50,53,70,51,7,117,110,105,50,53,70,52,7,117,110,105,50,53,70,53,7,117,110,105,50,53,70,54,7,117,110,105,50,53,70,55,7,117,110,105,50,53,70,56,7,117,110,105,50,53,70,57,7,117, +110,105,50,53,70,65,7,117,110,105,50,53,70,66,7,117,110,105,50,53,70,67,7,117,110,105,50,53,70,68,7,117,110,105,50,53,70,69,7,117,110,105,50,53,70,70,7,117,110,105,50,54,48,48,7,117,110,105,50,54,48,49,7,117,110,105,50,54,48,50,7,117,110,105,50,54,48, +51,7,117,110,105,50,54,48,52,7,117,110,105,50,54,48,53,7,117,110,105,50,54,48,54,7,117,110,105,50,54,48,55,7,117,110,105,50,54,48,56,7,117,110,105,50,54,48,57,7,117,110,105,50,54,48,65,7,117,110,105,50,54,48,66,7,117,110,105,50,54,48,67,7,117,110,105, +50,54,48,68,7,117,110,105,50,54,48,69,7,117,110,105,50,54,48,70,7,117,110,105,50,54,49,48,7,117,110,105,50,54,49,49,7,117,110,105,50,54,49,50,7,117,110,105,50,54,49,51,7,117,110,105,50,54,49,52,7,117,110,105,50,54,49,53,7,117,110,105,50,54,49,54,7,117, +110,105,50,54,49,55,7,117,110,105,50,54,49,56,7,117,110,105,50,54,49,57,7,117,110,105,50,54,49,65,7,117,110,105,50,54,49,66,7,117,110,105,50,54,49,67,7,117,110,105,50,54,49,68,7,117,110,105,50,54,49,69,7,117,110,105,50,54,49,70,7,117,110,105,50,54,50, +48,7,117,110,105,50,54,50,49,7,117,110,105,50,54,50,50,7,117,110,105,50,54,50,51,7,117,110,105,50,54,50,52,7,117,110,105,50,54,50,53,7,117,110,105,50,54,50,54,7,117,110,105,50,54,50,55,7,117,110,105,50,54,50,56,7,117,110,105,50,54,50,57,7,117,110,105, +50,54,50,65,7,117,110,105,50,54,50,66,7,117,110,105,50,54,50,67,7,117,110,105,50,54,50,68,7,117,110,105,50,54,50,69,7,117,110,105,50,54,50,70,7,117,110,105,50,54,51,56,7,117,110,105,50,54,51,57,9,115,109,105,108,101,102,97,99,101,12,105,110,118,115,109, +105,108,101,102,97,99,101,3,115,117,110,7,117,110,105,50,54,51,68,7,117,110,105,50,54,51,69,7,117,110,105,50,54,51,70,6,102,101,109,97,108,101,7,117,110,105,50,54,52,49,4,109,97,108,101,7,117,110,105,50,54,52,51,7,117,110,105,50,54,52,52,7,117,110,105, +50,54,52,53,7,117,110,105,50,54,52,54,7,117,110,105,50,54,52,55,7,117,110,105,50,54,52,56,7,117,110,105,50,54,52,57,7,117,110,105,50,54,52,65,7,117,110,105,50,54,52,66,7,117,110,105,50,54,52,67,7,117,110,105,50,54,52,68,7,117,110,105,50,54,52,69,7,117, +110,105,50,54,52,70,7,117,110,105,50,54,53,48,7,117,110,105,50,54,53,49,7,117,110,105,50,54,53,50,7,117,110,105,50,54,53,51,7,117,110,105,50,54,53,52,7,117,110,105,50,54,53,53,7,117,110,105,50,54,53,54,7,117,110,105,50,54,53,55,7,117,110,105,50,54,53, +56,7,117,110,105,50,54,53,57,7,117,110,105,50,54,53,65,7,117,110,105,50,54,53,66,7,117,110,105,50,54,53,67,7,117,110,105,50,54,53,68,7,117,110,105,50,54,53,69,7,117,110,105,50,54,53,70,5,115,112,97,100,101,7,117,110,105,50,54,54,49,7,117,110,105,50,54, +54,50,4,99,108,117,98,7,117,110,105,50,54,54,52,5,104,101,97,114,116,7,100,105,97,109,111,110,100,7,117,110,105,50,54,54,55,7,117,110,105,50,54,54,56,7,117,110,105,50,54,54,57,11,109,117,115,105,99,97,108,110,111,116,101,14,109,117,115,105,99,97,108, +110,111,116,101,100,98,108,7,117,110,105,50,54,54,67,7,117,110,105,50,54,54,68,7,117,110,105,50,54,54,69,7,117,110,105,50,54,54,70,7,117,110,105,50,54,55,48,7,117,110,105,50,54,55,49,7,117,110,105,50,54,55,50,7,117,110,105,50,54,55,51,7,117,110,105,50, +54,55,52,7,117,110,105,50,54,55,53,7,117,110,105,50,54,55,54,7,117,110,105,50,54,55,55,7,117,110,105,50,54,55,56,7,117,110,105,50,54,55,57,7,117,110,105,50,54,55,65,7,117,110,105,50,54,55,66,7,117,110,105,50,54,55,67,7,117,110,105,50,54,55,68,7,117,110, +105,50,54,55,69,7,117,110,105,50,54,55,70,7,117,110,105,50,54,56,48,7,117,110,105,50,54,56,49,7,117,110,105,50,54,56,50,7,117,110,105,50,54,56,51,7,117,110,105,50,54,56,52,7,117,110,105,50,54,56,53,7,117,110,105,50,54,56,54,7,117,110,105,50,54,56,55, +7,117,110,105,50,54,56,56,7,117,110,105,50,54,56,57,7,117,110,105,50,54,56,65,7,117,110,105,50,54,56,66,7,117,110,105,50,54,57,48,7,117,110,105,50,54,57,49,7,117,110,105,50,54,57,50,7,117,110,105,50,54,57,51,7,117,110,105,50,54,57,52,7,117,110,105,50, +54,57,53,7,117,110,105,50,54,57,54,7,117,110,105,50,54,57,55,7,117,110,105,50,54,57,56,7,117,110,105,50,54,57,57,7,117,110,105,50,54,57,65,7,117,110,105,50,54,57,66,7,117,110,105,50,54,57,67,7,117,110,105,50,54,65,48,7,117,110,105,50,54,65,49,7,117,110, +105,50,54,66,48,7,117,110,105,50,54,66,49,7,117,110,105,50,55,48,49,7,117,110,105,50,55,48,50,7,117,110,105,50,55,48,51,7,117,110,105,50,55,48,52,7,117,110,105,50,55,48,54,7,117,110,105,50,55,48,55,7,117,110,105,50,55,48,56,7,117,110,105,50,55,48,57, +7,117,110,105,50,55,48,67,7,117,110,105,50,55,48,68,7,117,110,105,50,55,48,69,7,117,110,105,50,55,48,70,7,117,110,105,50,55,49,48,7,117,110,105,50,55,49,49,7,117,110,105,50,55,49,50,7,117,110,105,50,55,49,51,7,117,110,105,50,55,49,52,7,117,110,105,50, +55,49,53,7,117,110,105,50,55,49,54,7,117,110,105,50,55,49,55,7,117,110,105,50,55,49,56,7,117,110,105,50,55,49,57,7,117,110,105,50,55,49,65,7,117,110,105,50,55,49,66,7,117,110,105,50,55,49,67,7,117,110,105,50,55,49,68,7,117,110,105,50,55,49,69,7,117,110, +105,50,55,49,70,7,117,110,105,50,55,50,48,7,117,110,105,50,55,50,49,7,117,110,105,50,55,50,50,7,117,110,105,50,55,50,51,7,117,110,105,50,55,50,52,7,117,110,105,50,55,50,53,7,117,110,105,50,55,50,54,7,117,110,105,50,55,50,55,7,117,110,105,50,55,50,57, +7,117,110,105,50,55,50,65,7,117,110,105,50,55,50,66,7,117,110,105,50,55,50,67,7,117,110,105,50,55,50,68,7,117,110,105,50,55,50,69,7,117,110,105,50,55,50,70,7,117,110,105,50,55,51,48,7,117,110,105,50,55,51,49,7,117,110,105,50,55,51,50,7,117,110,105,50, +55,51,51,7,117,110,105,50,55,51,52,7,117,110,105,50,55,51,53,7,117,110,105,50,55,51,54,7,117,110,105,50,55,51,55,7,117,110,105,50,55,51,56,7,117,110,105,50,55,51,57,7,117,110,105,50,55,51,65,7,117,110,105,50,55,51,66,7,117,110,105,50,55,51,67,7,117,110, +105,50,55,51,68,7,117,110,105,50,55,51,69,7,117,110,105,50,55,51,70,7,117,110,105,50,55,52,48,7,117,110,105,50,55,52,49,7,117,110,105,50,55,52,50,7,117,110,105,50,55,52,51,7,117,110,105,50,55,52,52,7,117,110,105,50,55,52,53,7,117,110,105,50,55,52,54, +7,117,110,105,50,55,52,55,7,117,110,105,50,55,52,56,7,117,110,105,50,55,52,57,7,117,110,105,50,55,52,65,7,117,110,105,50,55,52,66,7,117,110,105,50,55,52,68,7,117,110,105,50,55,52,70,7,117,110,105,50,55,53,48,7,117,110,105,50,55,53,49,7,117,110,105,50, +55,53,50,7,117,110,105,50,55,53,54,7,117,110,105,50,55,53,56,7,117,110,105,50,55,53,57,7,117,110,105,50,55,53,65,7,117,110,105,50,55,53,66,7,117,110,105,50,55,53,67,7,117,110,105,50,55,53,68,7,117,110,105,50,55,53,69,7,117,110,105,50,55,54,49,7,117,110, +105,50,55,54,50,7,117,110,105,50,55,54,51,7,117,110,105,50,55,54,52,7,117,110,105,50,55,54,53,7,117,110,105,50,55,54,54,7,117,110,105,50,55,54,55,7,117,110,105,50,55,54,56,7,117,110,105,50,55,54,57,7,117,110,105,50,55,54,65,7,117,110,105,50,55,54,66, +7,117,110,105,50,55,54,67,7,117,110,105,50,55,54,68,7,117,110,105,50,55,54,69,7,117,110,105,50,55,54,70,7,117,110,105,50,55,55,48,7,117,110,105,50,55,55,49,7,117,110,105,50,55,55,50,7,117,110,105,50,55,55,51,7,117,110,105,50,55,55,52,7,117,110,105,50, +55,55,53,7,117,110,105,50,55,57,52,7,117,110,105,50,55,57,56,7,117,110,105,50,55,57,57,7,117,110,105,50,55,57,65,7,117,110,105,50,55,57,66,7,117,110,105,50,55,57,67,7,117,110,105,50,55,57,68,7,117,110,105,50,55,57,69,7,117,110,105,50,55,57,70,7,117,110, +105,50,55,65,48,7,117,110,105,50,55,65,49,7,117,110,105,50,55,65,50,7,117,110,105,50,55,65,51,7,117,110,105,50,55,65,52,7,117,110,105,50,55,65,53,7,117,110,105,50,55,65,54,7,117,110,105,50,55,65,55,7,117,110,105,50,55,65,56,7,117,110,105,50,55,65,57, +7,117,110,105,50,55,65,65,7,117,110,105,50,55,65,66,7,117,110,105,50,55,65,67,7,117,110,105,50,55,65,68,7,117,110,105,50,55,65,69,7,117,110,105,50,55,65,70,7,117,110,105,50,55,66,49,7,117,110,105,50,55,66,50,7,117,110,105,50,55,66,51,7,117,110,105,50, +55,66,52,7,117,110,105,50,55,66,53,7,117,110,105,50,55,66,54,7,117,110,105,50,55,66,55,7,117,110,105,50,55,66,56,7,117,110,105,50,55,66,57,7,117,110,105,50,55,66,65,7,117,110,105,50,55,66,66,7,117,110,105,50,55,66,67,7,117,110,105,50,55,66,68,7,117,110, +105,50,55,66,69,7,117,110,105,50,55,67,50,7,117,110,105,50,55,67,53,7,117,110,105,50,55,67,54,7,117,110,105,50,55,68,67,7,117,110,105,50,55,69,48,7,117,110,105,50,55,69,54,7,117,110,105,50,55,69,55,7,117,110,105,50,55,69,56,7,117,110,105,50,55,69,57, +7,117,110,105,50,55,69,65,7,117,110,105,50,55,69,66,7,117,110,105,50,55,70,53,7,117,110,105,50,55,70,54,7,117,110,105,50,55,70,55,7,117,110,105,50,57,56,55,7,117,110,105,50,57,56,56,7,117,110,105,50,57,57,55,7,117,110,105,50,57,57,56,7,117,110,105,50, +57,69,66,7,117,110,105,50,57,70,65,7,117,110,105,50,57,70,66,7,117,110,105,50,65,48,48,7,117,110,105,50,65,50,70,7,117,110,105,50,65,54,65,7,117,110,105,50,65,54,66,7,117,110,105,50,66,48,53,7,117,110,105,50,66,48,54,7,117,110,105,50,66,48,55,7,117,110, +105,50,66,48,56,7,117,110,105,50,66,48,57,7,117,110,105,50,66,48,65,7,117,110,105,50,66,48,66,7,117,110,105,50,66,48,67,7,117,110,105,50,66,48,68,7,117,110,105,50,66,49,50,7,117,110,105,50,66,49,51,7,117,110,105,50,66,49,52,7,117,110,105,50,66,49,53, +7,117,110,105,50,66,49,54,7,117,110,105,50,66,49,55,7,117,110,105,50,66,49,56,7,117,110,105,50,66,49,57,7,117,110,105,50,66,49,65,7,117,110,105,50,67,54,52,7,117,110,105,50,67,54,68,7,117,110,105,50,67,54,69,7,117,110,105,50,67,54,70,7,117,110,105,50, +67,55,48,7,117,110,105,50,67,55,53,7,117,110,105,50,67,55,54,7,117,110,105,50,67,55,55,7,117,110,105,50,67,55,57,7,117,110,105,50,67,55,65,7,117,110,105,50,67,55,67,7,117,110,105,50,67,55,68,7,117,110,105,50,67,55,69,7,117,110,105,50,67,55,70,7,117,110, +105,50,69,49,56,7,117,110,105,50,69,49,70,7,117,110,105,50,69,50,50,7,117,110,105,50,69,50,51,7,117,110,105,50,69,50,52,7,117,110,105,50,69,50,53,7,117,110,105,50,69,50,69,7,117,110,105,65,55,48,56,7,117,110,105,65,55,48,57,7,117,110,105,65,55,48,65, +7,117,110,105,65,55,48,66,7,117,110,105,65,55,48,67,7,117,110,105,65,55,48,68,7,117,110,105,65,55,48,69,7,117,110,105,65,55,48,70,7,117,110,105,65,55,49,48,7,117,110,105,65,55,49,49,7,117,110,105,65,55,49,50,7,117,110,105,65,55,49,51,7,117,110,105,65, +55,49,52,7,117,110,105,65,55,49,53,7,117,110,105,65,55,49,54,7,117,110,105,65,55,49,66,7,117,110,105,65,55,49,67,7,117,110,105,65,55,49,68,7,117,110,105,65,55,49,69,7,117,110,105,65,55,49,70,7,117,110,105,65,55,50,50,7,117,110,105,65,55,50,51,7,117,110, +105,65,55,50,52,7,117,110,105,65,55,50,53,7,117,110,105,65,55,50,54,7,117,110,105,65,55,50,55,7,117,110,105,65,55,56,57,7,117,110,105,65,55,56,65,7,117,110,105,65,55,56,66,7,117,110,105,65,55,56,67,7,117,110,105,65,55,56,68,7,117,110,105,65,55,56,69, +7,117,110,105,65,55,57,48,7,117,110,105,65,55,57,49,7,117,110,105,65,55,65,65,7,117,110,105,65,55,70,56,7,117,110,105,65,55,70,57,7,117,110,105,70,54,67,53,7,117,110,105,70,66,53,50,7,117,110,105,70,66,53,51,7,117,110,105,70,66,53,52,7,117,110,105,70, +66,53,53,7,117,110,105,70,66,53,54,7,117,110,105,70,66,53,55,7,117,110,105,70,66,53,56,7,117,110,105,70,66,53,57,7,117,110,105,70,66,53,65,7,117,110,105,70,66,53,66,7,117,110,105,70,66,53,67,7,117,110,105,70,66,53,68,7,117,110,105,70,66,53,69,7,117,110, +105,70,66,53,70,7,117,110,105,70,66,54,48,7,117,110,105,70,66,54,49,7,117,110,105,70,66,54,50,7,117,110,105,70,66,54,51,7,117,110,105,70,66,54,52,7,117,110,105,70,66,54,53,7,117,110,105,70,66,54,54,7,117,110,105,70,66,54,55,7,117,110,105,70,66,54,56, +7,117,110,105,70,66,54,57,7,117,110,105,70,66,54,65,7,117,110,105,70,66,54,66,7,117,110,105,70,66,54,67,7,117,110,105,70,66,54,68,7,117,110,105,70,66,54,69,7,117,110,105,70,66,54,70,7,117,110,105,70,66,55,48,7,117,110,105,70,66,55,49,7,117,110,105,70, +66,55,50,7,117,110,105,70,66,55,51,7,117,110,105,70,66,55,52,7,117,110,105,70,66,55,53,7,117,110,105,70,66,55,54,7,117,110,105,70,66,55,55,7,117,110,105,70,66,55,56,7,117,110,105,70,66,55,57,7,117,110,105,70,66,55,65,7,117,110,105,70,66,55,66,7,117,110, +105,70,66,55,67,7,117,110,105,70,66,55,68,7,117,110,105,70,66,55,69,7,117,110,105,70,66,55,70,7,117,110,105,70,66,56,48,7,117,110,105,70,66,56,49,7,117,110,105,70,66,56,65,7,117,110,105,70,66,56,66,7,117,110,105,70,66,56,67,7,117,110,105,70,66,56,68, +7,117,110,105,70,66,56,69,7,117,110,105,70,66,56,70,7,117,110,105,70,66,57,48,7,117,110,105,70,66,57,49,7,117,110,105,70,66,57,50,7,117,110,105,70,66,57,51,7,117,110,105,70,66,57,52,7,117,110,105,70,66,57,53,7,117,110,105,70,66,57,69,7,117,110,105,70, +66,57,70,7,117,110,105,70,66,65,65,7,117,110,105,70,66,65,66,7,117,110,105,70,66,65,67,7,117,110,105,70,66,65,68,7,117,110,105,70,66,69,56,7,117,110,105,70,66,69,57,7,117,110,105,70,66,70,67,7,117,110,105,70,66,70,68,7,117,110,105,70,66,70,69,7,117,110, +105,70,66,70,70,7,117,110,105,70,69,55,48,7,117,110,105,70,69,55,49,7,117,110,105,70,69,55,50,7,117,110,105,70,69,55,51,7,117,110,105,70,69,55,52,7,117,110,105,70,69,55,54,7,117,110,105,70,69,55,55,7,117,110,105,70,69,55,56,7,117,110,105,70,69,55,57, +7,117,110,105,70,69,55,65,7,117,110,105,70,69,55,66,7,117,110,105,70,69,55,67,7,117,110,105,70,69,55,68,7,117,110,105,70,69,55,69,7,117,110,105,70,69,55,70,7,117,110,105,70,69,56,48,7,117,110,105,70,69,56,49,7,117,110,105,70,69,56,50,7,117,110,105,70, +69,56,51,7,117,110,105,70,69,56,52,7,117,110,105,70,69,56,53,7,117,110,105,70,69,56,54,7,117,110,105,70,69,56,55,7,117,110,105,70,69,56,56,7,117,110,105,70,69,56,57,7,117,110,105,70,69,56,65,7,117,110,105,70,69,56,66,7,117,110,105,70,69,56,67,7,117,110, +105,70,69,56,68,7,117,110,105,70,69,56,69,7,117,110,105,70,69,56,70,7,117,110,105,70,69,57,48,7,117,110,105,70,69,57,49,7,117,110,105,70,69,57,50,7,117,110,105,70,69,57,51,7,117,110,105,70,69,57,52,7,117,110,105,70,69,57,53,7,117,110,105,70,69,57,54, +7,117,110,105,70,69,57,55,7,117,110,105,70,69,57,56,7,117,110,105,70,69,57,57,7,117,110,105,70,69,57,65,7,117,110,105,70,69,57,66,7,117,110,105,70,69,57,67,7,117,110,105,70,69,57,68,7,117,110,105,70,69,57,69,7,117,110,105,70,69,57,70,7,117,110,105,70, +69,65,48,7,117,110,105,70,69,65,49,7,117,110,105,70,69,65,50,7,117,110,105,70,69,65,51,7,117,110,105,70,69,65,52,7,117,110,105,70,69,65,53,7,117,110,105,70,69,65,54,7,117,110,105,70,69,65,55,7,117,110,105,70,69,65,56,7,117,110,105,70,69,65,57,7,117,110, +105,70,69,65,65,7,117,110,105,70,69,65,66,7,117,110,105,70,69,65,67,7,117,110,105,70,69,65,68,7,117,110,105,70,69,65,69,7,117,110,105,70,69,65,70,7,117,110,105,70,69,66,48,7,117,110,105,70,69,66,49,7,117,110,105,70,69,66,50,7,117,110,105,70,69,66,51, +7,117,110,105,70,69,66,52,7,117,110,105,70,69,66,53,7,117,110,105,70,69,66,54,7,117,110,105,70,69,66,55,7,117,110,105,70,69,66,56,7,117,110,105,70,69,66,57,7,117,110,105,70,69,66,65,7,117,110,105,70,69,66,66,7,117,110,105,70,69,66,67,7,117,110,105,70, +69,66,68,7,117,110,105,70,69,66,69,7,117,110,105,70,69,66,70,7,117,110,105,70,69,67,48,7,117,110,105,70,69,67,49,7,117,110,105,70,69,67,50,7,117,110,105,70,69,67,51,7,117,110,105,70,69,67,52,7,117,110,105,70,69,67,53,7,117,110,105,70,69,67,54,7,117,110, +105,70,69,67,55,7,117,110,105,70,69,67,56,7,117,110,105,70,69,67,57,7,117,110,105,70,69,67,65,7,117,110,105,70,69,67,66,7,117,110,105,70,69,67,67,7,117,110,105,70,69,67,68,7,117,110,105,70,69,67,69,7,117,110,105,70,69,67,70,7,117,110,105,70,69,68,48, +7,117,110,105,70,69,68,49,7,117,110,105,70,69,68,50,7,117,110,105,70,69,68,51,7,117,110,105,70,69,68,52,7,117,110,105,70,69,68,53,7,117,110,105,70,69,68,54,7,117,110,105,70,69,68,55,7,117,110,105,70,69,68,56,7,117,110,105,70,69,68,57,7,117,110,105,70, +69,68,65,7,117,110,105,70,69,68,66,7,117,110,105,70,69,68,67,7,117,110,105,70,69,68,68,7,117,110,105,70,69,68,69,7,117,110,105,70,69,68,70,7,117,110,105,70,69,69,48,7,117,110,105,70,69,69,49,7,117,110,105,70,69,69,50,7,117,110,105,70,69,69,51,7,117,110, +105,70,69,69,52,7,117,110,105,70,69,69,53,7,117,110,105,70,69,69,54,7,117,110,105,70,69,69,55,7,117,110,105,70,69,69,56,7,117,110,105,70,69,69,57,7,117,110,105,70,69,69,65,7,117,110,105,70,69,69,66,7,117,110,105,70,69,69,67,7,117,110,105,70,69,69,68, +7,117,110,105,70,69,69,69,7,117,110,105,70,69,69,70,7,117,110,105,70,69,70,48,7,117,110,105,70,69,70,49,7,117,110,105,70,69,70,50,7,117,110,105,70,69,70,51,7,117,110,105,70,69,70,52,7,117,110,105,70,69,70,53,7,117,110,105,70,69,70,54,7,117,110,105,70, +69,70,55,7,117,110,105,70,69,70,56,7,117,110,105,70,69,70,57,7,117,110,105,70,69,70,65,7,117,110,105,70,69,70,66,7,117,110,105,70,69,70,67,7,117,110,105,70,69,70,70,7,117,110,105,70,70,70,57,7,117,110,105,70,70,70,65,7,117,110,105,70,70,70,66,7,117,110, +105,70,70,70,67,7,117,110,105,70,70,70,68,6,117,49,68,53,53,65,6,117,49,68,54,55,48,6,117,49,68,54,55,49,6,117,49,68,54,55,50,6,117,49,68,54,55,51,6,117,49,68,54,55,52,6,117,49,68,54,55,53,6,117,49,68,54,55,54,6,117,49,68,54,55,55,6,117,49,68,54,55,56, +6,117,49,68,54,55,57,6,117,49,68,54,55,65,6,117,49,68,54,55,66,6,117,49,68,54,55,67,6,117,49,68,54,55,68,6,117,49,68,54,55,69,6,117,49,68,54,55,70,6,117,49,68,54,56,48,6,117,49,68,54,56,49,6,117,49,68,54,56,50,6,117,49,68,54,56,51,6,117,49,68,54,56,52, +6,117,49,68,54,56,53,6,117,49,68,54,56,54,6,117,49,68,54,56,55,6,117,49,68,54,56,56,6,117,49,68,54,56,57,6,117,49,68,54,56,65,6,117,49,68,54,56,66,6,117,49,68,54,56,67,6,117,49,68,54,56,68,6,117,49,68,54,56,69,6,117,49,68,54,56,70,6,117,49,68,54,57,48, +6,117,49,68,54,57,49,6,117,49,68,54,57,50,6,117,49,68,54,57,51,6,117,49,68,54,57,52,6,117,49,68,54,57,53,6,117,49,68,54,57,54,6,117,49,68,54,57,55,6,117,49,68,54,57,56,6,117,49,68,54,57,57,6,117,49,68,54,57,65,6,117,49,68,54,57,66,6,117,49,68,54,57,67, +6,117,49,68,54,57,68,6,117,49,68,54,57,69,6,117,49,68,54,57,70,6,117,49,68,54,65,48,6,117,49,68,54,65,49,6,117,49,68,54,65,50,6,117,49,68,54,65,51,6,117,49,68,55,70,54,6,117,49,68,55,70,55,6,117,49,68,55,70,56,6,117,49,68,55,70,57,6,117,49,68,55,70,65, +6,117,49,68,55,70,66,6,117,49,68,55,70,67,6,117,49,68,55,70,68,6,117,49,68,55,70,69,6,117,49,68,55,70,70,9,100,108,76,116,99,97,114,111,110,9,68,105,97,101,114,101,115,105,115,5,65,99,117,116,101,5,84,105,108,100,101,5,71,114,97,118,101,10,67,105,114, +99,117,109,102,108,101,120,5,67,97,114,111,110,13,102,114,97,99,116,105,111,110,115,108,97,115,104,12,117,110,105,48,51,49,49,46,99,97,115,101,12,117,110,105,48,51,48,54,46,99,97,115,101,12,117,110,105,48,51,48,55,46,99,97,115,101,12,117,110,105,48,51, +48,66,46,99,97,115,101,12,117,110,105,48,51,48,70,46,99,97,115,101,12,116,104,105,110,113,117,101,115,116,105,111,110,12,117,110,105,48,51,48,52,46,99,97,115,101,8,117,110,100,101,114,98,97,114,13,117,110,100,101,114,98,97,114,46,119,105,100,101,14,117, +110,100,101,114,98,97,114,46,115,109,97,108,108,3,106,111,116,17,100,105,97,101,114,101,115,105,115,46,115,121,109,98,111,108,115,10,97,114,97,98,105,99,95,100,111,116,12,97,114,97,98,105,99,95,50,100,111,116,115,12,97,114,97,98,105,99,95,51,100,111, +116,115,12,117,110,105,48,54,54,69,46,102,105,110,97,12,117,110,105,48,54,65,49,46,105,110,105,116,12,117,110,105,48,54,65,49,46,109,101,100,105,12,117,110,105,48,54,54,70,46,102,105,110,97,12,117,110,105,48,54,65,49,46,102,105,110,97,14,97,114,97,98, +105,99,95,51,100,111,116,115,95,97,14,97,114,97,98,105,99,95,50,100,111,116,115,95,97,12,97,114,97,98,105,99,95,52,100,111,116,115,14,97,114,97,98,105,99,95,103,97,102,95,98,97,114,16,97,114,97,98,105,99,95,103,97,102,95,98,97,114,95,97,11,97,114,97, +98,105,99,95,114,105,110,103,7,69,110,103,46,97,108,116,7,117,110,105,48,54,54,69,7,117,110,105,48,54,54,70,7,117,110,105,48,54,55,67,7,117,110,105,48,54,55,68,7,117,110,105,48,54,56,49,7,117,110,105,48,54,56,50,7,117,110,105,48,54,56,53,7,117,110,105, +48,54,57,50,7,117,110,105,48,54,65,49,7,117,110,105,48,54,66,53,7,117,110,105,48,54,66,65,7,117,110,105,48,54,67,54,7,117,110,105,48,54,67,69,7,117,110,105,48,54,68,53,15,101,120,99,108,97,109,100,111,119,110,46,99,97,115,101,17,113,117,101,115,116,105, +111,110,100,111,119,110,46,99,97,115,101,12,117,110,105,50,69,49,56,46,99,97,115,101,0,0,0,185,2,128,1,21,178,148,93,5,65,28,1,21,0,150,0,3,1,21,0,128,0,4,1,20,0,254,0,3,1,19,0,254,0,3,1,18,0,18,0,3,1,17,0,254,0,3,1,16,0,254,0,3,1,15,0,154,0,3,1,14,0, +254,0,3,1,13,178,235,71,5,65,37,1,13,0,125,0,3,1,12,0,37,0,3,1,11,0,50,0,3,1,10,0,150,0,3,1,9,0,254,0,3,1,8,0,14,0,3,1,7,0,254,0,3,1,6,0,37,0,3,1,5,0,254,0,3,1,4,0,14,0,3,1,3,0,37,0,3,1,2,0,254,0,3,1,1,64,89,254,3,254,254,3,253,125,3,252,254,3,251,254, +3,250,50,3,249,187,3,248,125,3,247,246,140,5,247,254,3,247,192,4,246,245,89,5,246,140,3,246,128,4,245,244,38,5,245,89,3,245,64,4,244,38,3,243,242,47,5,243,250,3,242,47,3,241,254,3,240,254,3,239,50,3,238,20,3,237,150,3,236,235,71,5,236,254,3,236,184,255, +209,64,255,4,235,71,3,234,233,100,5,234,150,3,233,100,3,232,254,3,231,230,27,5,231,254,3,230,27,3,229,254,3,228,107,3,227,254,3,226,187,3,225,224,25,5,225,250,3,224,25,3,223,150,3,222,254,3,221,254,3,220,219,21,5,220,254,3,219,21,3,218,150,3,217,216, +21,5,217,254,3,216,141,11,5,216,21,3,215,125,3,214,58,3,213,141,11,5,213,58,3,212,254,3,211,210,10,5,211,254,3,210,10,3,209,254,3,208,254,3,207,138,17,5,207,28,3,206,22,3,205,254,3,204,150,3,203,139,37,5,203,254,3,202,254,3,201,125,3,200,254,3,199,254, +3,198,254,3,197,154,13,5,196,254,3,195,254,3,194,254,3,193,254,3,192,141,11,5,192,20,3,191,12,3,190,189,187,5,190,254,3,189,188,93,5,189,187,3,189,128,4,188,187,37,5,188,93,3,188,64,4,187,37,3,186,254,3,185,150,3,184,143,65,5,183,254,3,182,143,65,5,182, +250,3,181,154,13,5,180,254,3,179,100,3,178,100,3,177,14,3,176,18,3,175,254,3,174,254,64,253,3,173,254,3,172,254,3,171,18,3,170,254,3,169,168,14,5,169,50,3,168,14,3,167,166,17,5,167,40,3,166,17,3,165,164,45,5,165,125,3,164,45,3,163,254,3,162,254,3,161, +254,3,160,159,25,5,160,100,3,159,158,16,5,159,25,3,158,16,3,157,10,3,156,254,3,155,154,13,5,155,254,3,154,13,3,153,152,46,5,153,254,3,152,46,3,151,143,65,5,151,150,3,150,149,187,5,150,254,3,149,148,93,5,149,187,3,149,128,4,148,144,37,5,148,93,3,148,64, +4,147,254,3,146,254,3,145,144,37,5,145,187,3,144,37,3,143,139,37,5,143,65,3,142,141,11,5,142,20,3,141,11,3,140,139,37,5,140,100,3,139,138,17,5,139,37,3,138,17,3,137,254,3,136,254,3,135,254,3,134,133,17,5,134,254,3,133,17,3,132,254,3,131,254,3,130,17, +66,5,130,83,3,129,254,3,128,120,3,127,126,125,5,127,254,3,126,125,3,125,30,3,124,254,3,123,14,3,122,254,3,119,254,3,118,254,3,117,116,12,5,117,15,3,117,184,1,0,64,218,4,116,12,3,116,192,4,115,18,3,115,64,4,114,254,3,113,254,3,112,254,3,111,110,83,5,111, +150,3,110,109,40,5,110,83,3,109,40,3,108,254,3,107,50,3,106,254,3,105,50,3,104,250,3,103,187,3,102,254,3,101,254,3,100,254,3,99,98,30,5,99,254,3,98,0,16,5,98,30,3,97,254,3,96,254,3,95,254,3,94,90,11,5,94,14,3,93,100,3,92,200,3,91,90,11,5,91,20,3,90,11, +3,89,254,3,88,20,3,87,254,3,86,254,3,85,27,25,5,85,50,3,84,254,3,83,254,3,82,254,3,81,125,3,80,254,3,79,20,3,78,254,3,77,1,45,5,77,254,3,76,187,3,75,40,3,74,73,24,5,74,55,3,73,67,18,5,73,24,3,72,69,24,5,72,254,3,71,67,18,5,71,100,3,70,69,24,5,70,187, +3,69,24,3,68,67,18,5,68,55,3,67,66,17,5,67,18,3,67,184,2,64,64,9,4,66,65,15,5,66,17,3,66,184,2,0,64,9,4,65,64,14,5,65,15,3,65,184,1,192,64,9,4,64,63,12,5,64,14,3,64,184,1,128,64,9,4,63,12,9,5,63,12,3,63,184,1,64,64,100,4,62,254,3,61,1,45,5,61,250,3,60, +254,3,59,40,3,58,254,3,57,17,66,5,57,100,3,56,49,26,5,56,75,3,55,254,3,54,45,20,5,54,254,3,53,75,3,52,48,26,5,52,75,3,51,48,26,5,51,254,3,50,17,66,5,50,254,3,49,45,20,5,49,26,3,48,26,3,47,45,20,5,47,24,3,46,9,22,5,46,187,3,45,44,19,5,45,20,3,45,184,2, +128,64,9,4,44,16,17,5,44,19,3,44,184,2,64,64,150,4,43,42,37,5,43,254,3,42,9,22,5,42,37,3,41,2,58,5,41,254,3,40,254,3,39,254,3,38,15,3,37,22,66,5,37,69,3,36,15,3,35,254,3,34,15,15,5,34,254,3,33,32,45,5,33,125,3,32,45,3,31,75,3,30,17,66,5,30,254,3,29,254, +3,28,27,25,5,28,254,3,27,0,16,5,27,25,3,26,254,3,25,254,3,24,254,3,23,22,66,5,23,70,3,22,21,45,5,22,66,3,21,20,16,5,21,45,3,20,16,3,19,0,16,5,19,20,3,18,17,66,5,18,254,3,17,1,45,5,17,66,3,16,15,15,5,16,17,3,16,184,2,0,64,9,4,15,14,12,5,15,15,3,15,184, +1,192,64,9,4,14,13,10,5,14,12,3,14,184,1,128,64,9,4,13,12,9,5,13,10,3,13,184,1,64,180,4,12,9,3,12,184,1,0,64,55,4,11,254,3,10,9,22,5,10,254,3,9,22,3,8,16,3,7,254,3,6,1,45,5,6,254,3,5,20,3,3,2,58,5,3,250,3,2,1,45,5,2,58,3,1,0,16,5,1,45,3,0,16,3,1,184, +1,100,133,141,1,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, +43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, +43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,0,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, +43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, +43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,29,0,0,0 }; + +const char* DejaVuSansMono_ttf = (const char*) temp_binary_data_3; + +//================== copy.png ================== +static const unsigned char temp_binary_data_4[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,0,0,0,2,0,8,3,0,0,0,195,166,36,200,0,0,0,3,115,66,73,84,8,8,8,219,225,79,224,0,0,0,9,112,72,89,115,0,0,14,131,0,0,14,131,1,56,78,237,13,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119, +119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,2,139,80,76,84,69,255,255,255,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,142,61,39,0,0,0,216,116,82,78,83,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,24,25,28,29, +30,31,32,33,34,36,37,38,39,40,41,42,43,44,45,48,49,51,52,53,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,75,76,77,78,80,81,82,83,84,85,86,88,90,91,92,93,95,96,97,98,101,102,104,106,107,108,109,110,111,112,113,114,116,117,118,119,120,121,122, +123,124,126,127,128,129,130,131,132,135,137,138,139,142,143,144,146,147,148,149,150,151,152,153,154,156,159,160,161,162,163,164,165,166,167,168,169,170,171,172,174,175,176,177,179,180,181,183,184,185,186,187,188,189,190,191,192,193,194,197,198,199,202, +203,204,205,206,207,208,210,211,212,214,215,216,217,218,219,220,221,222,223,224,225,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,10,6,38,255,0,0,12,5,73,68,65,84,120,218,237,221,11,151, +149,85,29,7,224,61,195,76,32,50,130,35,8,162,162,53,64,48,153,105,101,166,230,5,24,211,68,3,69,17,144,52,50,80,1,65,203,74,13,185,40,130,87,200,164,171,8,130,133,104,154,23,212,160,18,98,194,20,152,65,112,102,224,124,156,166,203,114,121,97,246,185,172, +5,195,217,251,249,125,128,179,206,127,255,158,245,190,251,188,151,153,16,170,41,181,205,19,166,206,95,178,102,243,142,174,66,78,233,218,177,121,205,146,249,83,39,52,215,134,156,211,111,252,178,214,66,222,105,93,54,190,95,166,237,15,154,180,186,189,32, +133,66,251,234,73,131,242,171,191,105,85,167,234,63,74,231,170,166,188,234,31,186,88,253,159,34,176,120,104,62,245,55,44,116,236,63,204,153,96,97,67,30,245,215,207,220,165,237,195,102,215,204,250,12,250,31,178,81,211,61,102,227,144,228,251,31,187,77, +205,145,108,27,155,120,255,45,109,74,142,166,173,37,233,254,103,31,84,113,145,28,156,157,110,253,125,87,234,183,132,172,236,155,42,128,21,202,45,41,43,82,61,254,171,182,196,164,121,22,104,113,254,47,121,31,144,226,78,112,204,94,197,150,156,189,99,146, +235,127,240,86,181,150,145,173,131,19,235,191,110,131,82,203,202,134,186,180,0,76,83,105,153,153,158,84,255,3,118,106,180,204,180,38,117,111,112,158,66,203,206,130,132,250,63,217,29,128,242,179,111,88,58,0,238,87,103,5,89,154,76,255,103,118,104,179,130, +116,141,74,5,192,99,202,172,40,79,37,210,127,195,135,186,172,40,157,39,166,1,96,162,42,43,204,164,52,0,60,170,201,10,179,42,137,254,235,119,23,159,244,95,191,187,107,226,229,57,101,226,93,191,125,183,248,178,180,37,241,104,200,37,197,198,60,112,251,25, +33,199,156,126,235,254,98,75,115,89,10,115,46,42,50,228,166,209,33,215,52,253,161,200,218,44,78,96,200,154,237,209,17,59,110,235,19,242,77,237,172,248,47,164,29,53,213,63,227,232,184,241,219,67,222,153,21,95,158,4,142,142,241,45,192,166,62,153,3,168, +141,159,5,46,173,254,9,175,141,205,183,127,84,200,61,77,209,157,224,148,234,31,112,78,108,190,31,6,185,53,182,64,119,84,255,124,247,198,230,27,161,255,112,122,108,129,22,85,255,124,171,35,227,189,167,254,238,196,222,150,127,186,250,199,123,62,50,222, +90,237,119,231,55,145,21,122,161,250,199,139,189,14,254,35,237,119,103,65,236,66,64,245,143,183,39,50,222,53,218,239,206,85,145,21,58,88,253,227,109,141,140,247,13,237,119,231,242,216,46,48,237,61,192,231,181,159,62,128,135,34,151,129,250,105,63,125, +0,87,37,253,27,7,128,162,137,60,17,120,157,242,51,0,16,150,246,52,219,206,227,149,159,3,128,97,251,178,120,253,17,128,30,211,195,221,142,151,235,117,159,7,128,240,196,225,38,251,231,105,170,207,5,64,255,195,252,117,136,247,191,166,249,108,0,132,250,207, +108,4,183,52,41,62,35,0,33,92,253,137,123,66,31,254,116,160,222,243,2,16,250,206,220,116,232,255,51,109,95,228,57,144,252,0,252,231,247,224,53,63,248,201,3,115,111,56,171,70,231,121,2,16,0,4,0,1,64,0,16,0,4,0,1,64,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,44,15,0,2,128,0,32,0,8,0,2,128,0,32,0,8,0,2,128,0,32,0,8,0,2,128,0,32,0,28,193,156,48,242,162,201,179,102,231,148,89,147,47,28,217,0,64,8,141,147,151,175,219,210,150,233,191,112,111,123,227,217,7,175,25,148,49,128,17,55,175,239,44,228,158, +142,103,102,12,207,18,64,211,194,87,10,242,191,188,56,119,68,110,0,134,45,233,210,251,199,255,190,229,207,6,231,4,160,97,65,187,206,63,149,221,115,142,203,5,64,221,180,86,125,31,38,239,92,95,155,5,128,243,222,212,117,15,249,243,151,51,0,48,181,67,209, +61,230,131,171,83,7,80,119,159,150,163,89,88,147,52,128,198,181,42,46,146,95,28,159,48,128,81,111,43,184,104,94,62,53,89,0,231,238,81,111,9,105,29,157,40,128,225,59,149,91,82,222,62,41,73,0,253,95,82,109,137,89,87,151,32,128,154,39,21,91,114,30,72,16, +192,92,181,150,145,233,201,1,184,226,144,86,203,72,231,183,18,3,112,134,187,63,229,229,189,161,105,1,120,92,165,189,177,13,56,102,0,156,237,4,80,246,73,224,11,41,1,88,175,208,178,179,58,33,0,227,212,89,65,190,146,12,128,62,175,106,179,130,108,72,6,192, +245,202,172,40,227,82,1,176,85,151,21,229,143,137,0,104,86,101,101,57,116,74,26,0,230,169,178,183,46,8,31,27,0,74,186,11,216,245,214,27,57,229,111,37,1,120,54,9,0,195,139,206,185,125,197,247,190,122,92,200,43,141,151,220,246,212,222,162,23,131,26,83, +0,48,163,216,153,110,209,128,144,103,78,253,125,49,1,215,166,0,224,153,248,140,219,46,12,249,102,106,145,131,192,47,19,0,48,48,254,30,192,218,1,33,231,156,22,223,12,124,208,191,250,1,156,19,157,112,247,41,33,239,92,28,63,4,52,87,63,128,43,163,3,78,9, +185,103,201,145,188,24,120,44,0,184,41,246,29,126,157,125,255,161,225,175,177,5,186,161,250,1,220,29,251,14,163,0,8,83,98,11,52,175,250,1,60,28,249,10,239,215,232,63,140,140,149,180,180,250,1,196,222,6,92,171,254,16,106,98,63,5,127,85,253,0,94,143,124, +133,187,213,31,226,143,75,253,169,250,1,196,222,7,188,82,251,221,185,39,178,66,173,213,15,32,246,21,206,209,126,119,110,142,172,208,126,0,242,6,112,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,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,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,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,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,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,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,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,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,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,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,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,0,0,4,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,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,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,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,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,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,0,0,4,0,0,0,0,0,0,0,142,0,128,233,145,143,222,3,64,250,0,30,140,124,244,235,0,164,15,224,213,200,71,175,5,32,121,0,199,119,69,62, +250,97,0,146,7,112,65,108,241,239,6,32,117,0,125,54,197,22,255,38,0,82,7,48,39,182,246,133,43,1,72,28,192,23,15,20,142,133,197,7,160,151,0,156,244,98,180,255,142,129,0,36,13,224,219,173,209,254,11,207,4,0,18,6,208,248,104,161,72,102,0,144,42,128,19,190, +57,235,241,93,197,250,47,12,7,32,61,0,53,103,207,127,100,221,91,135,10,37,228,165,0,64,106,0,142,187,109,123,161,228,204,3,32,53,0,19,223,41,148,145,102,0,210,2,80,251,227,114,234,47,108,13,0,36,5,160,230,137,178,250,47,92,15,64,90,0,238,42,175,255,87, +251,0,144,20,128,241,229,245,95,24,23,0,72,9,64,159,215,202,235,127,125,0,32,41,0,215,149,215,255,161,179,1,72,11,192,115,229,1,120,60,0,144,20,128,198,174,178,250,111,63,3,128,180,0,124,167,188,19,192,21,1,128,180,0,124,191,44,0,115,3,0,137,1,184,167, +156,254,159,172,1,32,53,0,139,203,232,255,165,254,1,128,212,0,220,89,122,255,59,135,7,0,146,3,112,99,201,253,239,57,55,0,144,30,128,175,151,218,255,219,163,2,0,9,2,232,243,110,105,253,175,109,12,0,36,121,37,112,121,73,253,223,87,23,0,72,19,64,115,9,143, +1,118,76,237,165,241,0,56,242,0,66,209,135,192,11,111,158,23,0,72,23,192,240,34,111,129,180,78,171,11,0,36,12,32,156,179,63,118,247,103,65,67,47,142,7,192,209,0,16,38,180,247,244,17,93,75,134,245,234,120,0,28,21,0,225,75,127,63,236,7,188,178,176,169, +151,199,3,224,232,0,8,141,247,124,250,52,208,185,254,230,17,189,63,30,0,71,9,64,8,167,204,251,232,141,240,182,45,235,150,79,110,60,38,198,3,224,168,1,232,206,176,243,191,123,203,228,139,70,158,112,12,141,7,192,209,4,112,12,6,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,64,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,122,37,7,35,227,93,160,253,238,204,137,172,208, +190,234,31,111,71,100,188,91,180,223,157,39,34,43,180,173,250,199,123,33,50,222,35,218,239,206,95,34,43,244,124,245,143,247,116,100,188,45,218,15,161,49,182,75,90,93,253,243,45,138,140,119,104,160,254,195,197,49,0,247,86,255,124,119,196,230,155,161,255, +176,50,182,64,115,170,127,190,41,177,249,218,71,100,223,127,75,244,191,62,95,91,253,3,94,26,29,240,185,154,220,119,0,255,136,174,207,37,213,63,225,232,248,63,54,207,253,36,176,50,190,60,163,171,127,194,154,29,209,9,59,238,168,203,184,254,19,31,142,247, +191,61,133,3,228,226,248,140,133,23,199,100,219,255,184,237,69,214,102,81,10,83,94,86,100,200,194,135,119,158,245,185,12,219,31,112,254,242,98,43,147,194,22,32,132,190,109,69,231,44,28,216,244,243,233,55,230,148,91,150,191,118,176,248,178,236,174,79, +130,250,170,130,84,150,71,211,56,214,77,210,100,133,153,152,200,86,183,83,149,21,229,64,67,34,219,157,167,116,89,81,30,75,101,191,59,170,75,153,21,164,227,204,100,126,241,44,213,102,5,185,63,157,159,188,195,246,169,179,236,180,157,156,208,69,143,5,250, +44,59,243,82,186,234,213,208,170,208,50,179,115,64,82,215,61,167,107,180,204,76,75,235,194,119,221,6,149,150,149,13,169,221,36,29,188,85,169,101,100,235,224,228,110,126,141,217,171,214,146,179,55,197,91,228,45,7,21,91,98,14,182,36,121,3,124,182,102,75, +204,236,68,31,129,88,161,218,146,178,34,213,103,96,250,174,84,110,9,89,217,55,221,199,160,102,219,7,20,61,255,207,14,41,167,165,77,197,241,59,0,45,33,237,140,221,166,228,72,182,141,13,169,103,200,70,53,247,152,141,67,66,250,169,159,185,75,211,135,205, +174,153,245,33,139,52,44,108,215,246,103,210,190,176,33,100,147,161,139,61,40,250,201,116,46,30,26,178,74,211,42,4,62,86,255,170,166,144,93,6,77,90,237,76,240,223,99,255,234,73,131,66,158,233,55,126,89,238,143,10,181,46,27,223,47,228,156,218,230,9,83, +231,47,89,179,121,71,94,143,142,119,237,216,188,102,201,252,169,19,154,107,171,170,173,127,3,217,192,72,154,199,230,175,22,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* copy_png = (const char*) temp_binary_data_4; + +//================== flower_center.png ================== +static const unsigned char temp_binary_data_5[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,0,0,0,2,0,8,6,0,0,0,244,120,212,250,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,223,9,12,14,31,51,16,110,155, +17,0,0,12,112,73,68,65,84,120,218,237,221,77,142,220,56,18,6,80,185,209,62,129,119,188,80,157,217,23,138,157,79,80,139,234,69,163,225,114,117,101,165,126,72,49,72,190,7,24,24,140,61,202,212,207,40,62,134,40,230,182,1,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,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,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,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,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,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,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,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,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,0,0,0,0,0,64,70,223,28,2,152,203,175,159,223,223,106,111,243,199,203,171,123,5,8,0,192,140,69,94,56,0,1,0,80,236,133,2,16,0,0,69,95,24,0,1,0,80,240,5,2,16, +0,0,133,95,16,0,1,0,80,244,133,1,16,0,0,69,95,24,0,1,0,20,126,4,1,16,0,64,225,71,16,0,1,0,20,126,4,1,16,0,64,225,71,16,0,1,0,20,127,132,0,16,0,96,154,194,95,190,248,187,104,188,19,61,63,91,16,0,1,0,150,30,241,151,39,127,223,170,16,247,250,92,65,0,82, +248,203,33,128,142,197,31,231,5,58,249,219,33,0,5,102,166,115,164,27,0,2,0,40,254,89,53,156,123,240,235,231,247,55,33,0,4,0,80,248,117,3,128,79,152,3,0,217,139,127,217,158,79,216,67,136,3,1,0,6,43,26,189,102,219,135,243,9,43,211,30,131,76,197,98,240, +247,242,51,239,167,199,1,32,0,64,222,81,226,68,239,230,103,13,58,130,0,252,203,35,0,20,255,35,197,223,179,120,97,15,116,0,96,226,98,208,107,132,186,74,7,32,1,157,0,116,0,64,241,199,249,7,1,0,220,252,47,142,210,175,48,194,23,2,64,0,0,55,125,92,15,208, +138,149,0,113,179,103,159,137,95,81,180,124,48,58,0,160,248,143,91,132,113,125,128,0,0,23,111,238,153,70,180,241,225,15,66,0,84,160,229,133,155,250,179,209,182,162,251,231,241,200,30,152,42,240,56,0,1,0,140,232,20,234,59,2,64,205,109,87,218,150,16,192, +236,60,2,0,225,192,254,129,0,0,70,255,224,250,65,0,0,55,111,92,71,48,37,235,0,224,166,157,93,150,201,119,177,238,245,100,62,0,58,0,48,122,241,47,31,254,204,200,91,11,66,37,232,0,192,102,98,216,74,194,249,6,29,0,140,210,248,93,20,71,93,72,40,242,108,203, +245,197,108,60,215,98,254,226,63,250,2,54,11,45,192,51,2,243,1,208,1,0,0,116,0,32,229,232,255,217,8,250,204,40,250,238,17,185,14,128,46,0,8,0,112,176,248,215,14,0,181,195,4,66,0,116,226,17,0,107,139,198,255,30,64,7,0,58,140,254,91,152,185,37,95,4,31, +93,0,116,0,128,181,120,127,30,4,0,48,250,87,68,25,248,58,4,1,0,55,93,112,61,194,103,44,5,12,87,173,240,124,188,108,230,1,192,100,76,96,193,104,139,223,69,126,245,160,115,129,9,129,232,0,0,8,53,160,3,0,70,255,55,22,184,72,182,189,197,2,128,46,0,58,0,64, +191,162,118,133,17,49,44,195,91,0,24,253,179,102,216,113,157,162,3,0,76,85,48,227,192,191,205,220,13,40,39,246,9,208,1,192,232,159,137,70,254,101,156,110,128,235,21,1,0,160,117,48,0,4,0,96,145,34,127,36,4,196,246,249,227,131,71,255,61,44,196,43,43,164, +166,157,122,160,8,70,133,109,92,217,222,93,35,252,65,10,183,87,2,201,206,36,64,24,81,76,188,95,218,252,112,11,143,0,152,115,116,60,208,164,49,14,132,27,109,123,168,70,139,138,180,118,183,255,139,130,145,54,136,93,57,39,19,172,74,232,49,0,58,0,192,26, +197,125,207,223,239,237,204,188,159,168,23,23,191,171,110,16,232,0,48,217,232,127,79,65,209,5,104,91,252,35,241,57,41,253,175,7,93,0,178,50,9,16,106,141,126,99,225,227,17,3,157,39,43,11,194,182,109,30,1,64,157,162,178,103,212,59,243,254,151,137,206,35, +8,0,0,7,138,102,25,232,187,2,2,0,249,28,94,252,71,59,87,65,61,42,18,95,207,112,19,115,0,112,67,63,250,57,173,139,97,198,57,6,123,246,59,146,93,15,186,0,32,0,192,50,35,237,150,107,34,196,129,112,18,79,190,95,205,137,120,229,196,126,0,30,1,144,139,118, +105,226,112,241,168,120,158,93,216,231,142,17,122,156,252,174,174,107,116,0,128,75,35,202,154,35,242,44,175,175,197,137,2,254,236,237,129,232,116,126,64,0,0,20,148,142,199,193,187,249,32,0,192,50,138,253,20,170,160,31,115,0,128,190,20,127,16,0,88,219, +116,19,165,106,141,240,99,251,243,135,113,20,120,215,55,84,224,17,0,204,84,48,35,249,62,181,248,137,95,1,3,116,0,128,129,194,141,194,13,58,0,176,212,72,190,56,46,128,14,0,64,30,150,15,70,7,0,6,188,97,71,227,237,215,250,28,35,224,220,215,82,113,158,16, +0,96,172,17,90,237,197,100,122,174,94,71,255,235,202,226,68,76,238,155,67,64,6,187,95,145,186,243,23,233,70,250,245,187,17,2,90,12,248,157,27,124,239,31,47,175,238,187,232,0,0,201,138,159,80,163,19,192,50,76,2,132,213,138,124,121,247,231,232,104,184, +156,252,187,81,142,205,13,29,0,16,0,224,12,55,227,115,5,174,52,222,86,113,61,129,0,0,130,72,238,145,127,239,109,141,116,46,5,4,4,0,88,180,200,143,90,0,202,77,219,154,57,4,40,254,76,206,36,64,140,190,179,143,246,179,207,172,159,229,57,250,251,223,43,80, +252,209,1,0,140,254,39,40,238,35,5,62,16,0,128,219,11,88,40,134,32,0,0,107,133,128,56,177,173,56,240,111,128,84,204,1,128,153,67,64,105,184,173,86,221,2,43,48,130,14,0,92,46,36,95,45,122,179,74,8,216,51,74,63,218,33,80,132,65,7,0,134,10,4,61,70,149,25, +102,241,183,8,1,128,0,0,67,21,251,171,219,92,237,53,68,64,0,0,1,162,241,231,40,246,199,142,153,227,5,167,153,3,0,8,106,32,0,192,130,122,61,255,199,49,134,142,60,2,64,33,88,245,152,100,109,159,199,137,125,41,201,247,9,116,0,64,208,16,98,28,23,208,1,128, +94,35,203,210,225,51,21,179,251,143,53,32,0,128,98,49,248,249,202,246,56,195,99,7,6,247,205,33,32,139,95,63,191,191,85,185,33,215,42,18,45,127,22,246,174,87,217,50,46,126,116,245,179,75,130,0,112,242,245,205,31,47,175,238,185,232,0,192,210,93,130,145, +71,141,189,71,190,177,245,93,11,160,232,6,48,7,147,0,81,176,249,186,216,61,250,77,133,146,224,92,71,194,227,5,58,0,32,8,48,217,121,86,224,17,0,64,81,232,90,108,132,28,197,31,46,242,8,0,20,27,106,133,75,193,12,1,0,104,30,16,202,13,65,65,65,251,255,241, +8,199,138,57,120,37,133,84,46,191,10,216,115,116,30,141,183,127,182,80,95,253,190,165,211,231,142,116,29,236,216,39,175,0,146,141,57,0,208,186,56,247,222,126,207,215,245,62,219,167,178,205,17,2,98,162,125,65,0,0,56,20,34,158,117,7,202,23,255,187,152, +248,184,192,0,204,1,128,44,178,78,252,139,70,251,83,58,30,231,178,153,104,137,0,224,16,192,228,5,156,199,231,200,57,67,0,128,28,150,158,40,21,246,183,107,71,192,117,141,0,0,116,45,138,113,160,88,198,118,238,71,142,106,20,188,43,63,248,147,113,21,63,221, +0,22,99,18,32,28,45,208,39,127,9,238,244,231,212,92,247,254,227,90,254,49,201,241,186,90,252,123,125,47,232,72,91,138,148,134,88,15,96,68,53,127,74,247,104,7,160,231,47,230,117,12,0,218,255,232,0,0,249,138,255,149,194,28,23,3,193,157,98,243,219,10,32, +0,128,226,223,172,200,102,246,104,97,34,197,159,69,153,4,8,138,255,125,33,33,83,16,184,90,252,173,37,192,224,60,155,34,173,174,243,0,102,107,23,215,254,125,1,161,106,215,177,242,252,159,204,60,2,96,185,155,114,149,207,25,173,56,198,98,163,252,187,195, +84,207,9,142,112,146,71,0,164,117,121,244,100,201,87,163,250,142,225,192,232,31,1,0,20,81,223,127,230,209,63,8,0,128,16,176,120,241,119,92,17,0,160,14,109,84,1,97,196,99,226,186,101,4,38,1,178,206,232,44,219,119,13,231,108,184,192,241,213,100,74,161, +9,1,0,38,27,237,213,12,23,229,201,118,163,211,62,246,14,108,163,189,89,17,131,6,24,120,71,155,138,33,236,90,19,96,132,119,247,51,47,151,155,225,24,196,128,251,242,225,59,107,255,163,3,0,61,71,237,140,87,252,71,237,4,192,160,76,2,100,8,75,140,170,20,19, +215,41,8,0,192,146,132,32,16,0,192,232,74,129,119,125,130,0,0,204,30,2,140,254,225,86,18,43,195,233,250,43,129,212,53,201,154,8,70,255,140,200,91,0,64,190,110,0,160,3,0,186,0,24,253,131,0,0,66,0,138,63,84,224,17,0,107,177,18,31,192,182,109,222,2,192, +232,139,61,161,169,56,12,174,63,116,0,128,181,138,255,103,255,249,63,58,38,160,3,0,70,97,201,71,240,197,254,187,238,64,0,64,8,88,115,52,91,22,15,4,37,209,245,6,2,0,192,141,5,223,124,6,16,0,208,5,96,209,209,254,201,14,136,235,12,1,0,70,13,1,241,225,15, +231,101,62,126,165,242,191,83,252,153,144,183,0,80,196,86,29,5,183,252,188,72,182,173,103,159,35,12,178,32,137,150,233,88,33,240,64,0,136,198,159,23,149,182,21,13,246,253,192,177,48,250,71,0,0,33,96,174,16,16,55,124,78,116,220,214,222,16,160,248,35,0, +128,16,64,131,209,118,116,218,214,197,109,42,254,8,0,32,4,208,112,148,221,100,91,123,183,173,248,179,40,111,1,0,237,69,130,109,69,227,239,5,58,0,176,96,23,224,174,231,236,35,118,1,34,225,177,124,50,243,223,232,31,29,0,152,64,243,155,185,149,229,114,140, +240,43,125,134,226,143,0,0,66,0,87,139,234,96,237,122,215,9,43,113,177,179,148,38,143,3,238,126,215,126,4,53,23,215,185,105,161,30,197,31,1,0,132,0,1,96,49,138,63,43,242,8,0,55,123,92,15,32,0,128,155,126,85,70,255,174,3,72,202,197,207,210,154,207,9,16, +0,20,127,16,0,96,161,16,144,65,205,31,230,81,252,65,0,0,33,96,208,0,32,12,40,254,32,0,64,194,32,144,253,7,117,20,126,152,138,73,128,160,72,56,175,32,0,0,138,133,243,9,2,0,40,26,56,143,48,37,255,231,128,39,110,155,23,112,215,47,234,157,217,158,194,15, +58,0,96,20,57,128,80,252,1,29,0,24,163,27,224,181,61,133,31,4,0,88,52,4,60,10,5,2,128,226,15,2,0,44,24,4,80,248,65,0,0,65,64,225,87,248,65,0,0,33,64,241,7,4,0,16,4,20,126,64,0,0,65,64,225,7,4,0,16,4,20,126,64,0,0,65,64,225,7,1,0,16,6,20,125,16,0,0,97, +64,209,7,1,0,16,4,20,126,16,0,0,129,64,193,7,1,0,16,6,20,125,16,0,128,101,66,129,98,15,2,0,48,105,56,80,228,1,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,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, +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,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,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,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,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,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,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,0,0,0,0,0, +0,0,0,104,228,31,147,91,47,206,240,210,17,157,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* flower_center_png = (const char*) temp_binary_data_5; + +//================== flower_petals.png ================== +static const unsigned char temp_binary_data_6[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,0,0,0,2,0,8,6,0,0,0,244,120,212,250,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,224,3,11,14,50,54,98,101,160, +17,0,0,32,0,73,68,65,84,120,218,237,189,61,139,36,91,180,37,182,118,113,25,198,120,204,205,246,158,241,160,163,153,135,24,239,102,123,18,188,161,163,97,92,81,121,145,37,16,84,148,39,75,93,23,198,239,236,31,32,170,26,253,128,202,178,198,236,44,70,150, +64,84,20,204,128,188,202,244,198,120,168,179,96,140,231,117,166,120,134,144,115,100,196,142,174,172,236,250,200,143,136,115,246,57,103,45,40,186,239,71,119,68,236,179,207,222,107,127,156,125,4,4,65,36,3,231,220,7,253,237,16,192,0,64,161,63,45,54,255, +121,29,11,253,217,252,231,37,128,25,0,136,200,45,165,76,16,105,64,40,2,130,136,214,217,15,1,252,1,160,84,135,63,244,244,232,25,128,90,127,157,139,200,140,171,65,16,36,0,4,65,244,231,240,7,0,142,213,225,143,52,194,183,128,37,128,169,146,130,107,17,89, +114,181,8,130,4,128,32,136,110,156,126,165,142,63,6,212,0,38,36,3,4,65,16,4,177,187,227,47,156,115,151,206,185,31,46,94,252,112,206,157,59,231,10,174,40,65,16,4,65,188,236,248,75,231,220,141,75,15,55,206,185,146,43,76,16,4,65,16,191,70,252,223,92,250, +184,100,70,128,32,8,130,160,227,119,110,160,105,242,220,112,174,253,13,4,65,4,2,155,0,9,34,156,243,47,1,124,131,157,110,126,223,88,0,56,21,145,154,218,64,16,254,113,68,17,16,68,16,231,127,14,224,38,99,231,15,52,3,137,110,156,115,159,169,17,4,193,12,0, +65,164,238,248,135,0,46,225,111,104,79,44,152,105,54,128,67,133,8,130,4,128,32,146,116,254,185,71,253,47,97,9,224,35,73,0,65,248,1,75,0,4,225,199,249,143,232,252,95,197,0,77,73,96,68,81,16,4,51,0,4,145,130,243,175,208,164,253,137,237,113,42,34,19,138, +129,32,72,0,8,130,206,159,36,128,32,8,18,0,130,160,243,207,4,127,138,200,148,98,32,8,18,0,130,136,197,249,179,225,175,27,176,49,144,32,72,0,8,34,26,231,95,0,184,163,243,239,148,4,188,23,145,5,69,65,16,221,129,167,0,8,162,123,228,60,221,175,15,12,84,166, +4,65,144,0,16,132,217,232,255,2,28,242,211,7,134,42,91,130,32,58,2,75,0,4,209,157,243,31,49,82,237,29,108,10,36,8,18,0,130,48,229,252,7,0,190,131,169,255,190,177,4,240,78,68,150,20,5,65,28,6,150,0,8,162,27,92,208,249,123,193,64,101,77,16,4,51,0,4,17, +60,250,47,209,28,249,35,252,225,35,175,17,38,8,18,0,130,8,77,0,238,192,198,63,223,152,137,200,123,138,129,32,72,0,8,155,142,113,8,224,119,52,247,190,23,79,252,47,75,52,215,192,182,152,199,86,219,53,60,237,239,30,64,13,96,177,246,211,108,250,103,34,103, +205,100,180,40,214,126,74,0,111,13,126,99,116,163,130,181,87,228,143,181,127,53,196,211,165,163,118,205,86,28,130,68,144,0,16,214,13,219,7,117,20,67,253,41,246,252,171,22,74,10,102,234,192,76,147,2,231,220,247,3,190,181,75,172,0,76,245,167,238,90,102, +234,184,74,0,35,253,249,221,192,55,47,68,228,93,4,206,190,243,125,33,34,183,180,58,4,65,4,139,238,157,115,159,157,115,55,174,127,220,57,231,62,169,65,53,21,253,187,240,152,105,22,34,196,183,207,12,124,127,101,76,39,10,213,213,59,15,223,126,163,123,144, +229,39,130,25,0,162,127,167,15,224,68,35,192,80,81,111,27,229,94,135,206,12,4,142,254,239,1,84,161,27,225,180,108,48,65,184,18,65,240,44,128,18,211,227,181,236,72,16,57,232,190,184,98,201,128,32,136,46,13,220,137,167,136,102,23,252,208,232,103,16,72, +38,33,163,255,11,75,217,16,231,220,64,223,41,171,44,128,70,251,151,206,30,238,156,115,39,180,92,4,65,28,98,220,62,171,163,181,140,32,68,192,83,233,99,19,75,107,41,239,39,72,209,50,128,92,110,2,236,141,75,103,31,237,222,40,104,209,8,130,72,201,184,5,35, +2,42,163,16,206,127,24,129,254,12,3,145,128,194,195,183,13,34,33,197,79,225,146,68,128,32,136,212,28,255,83,68,96,212,179,172,46,232,252,95,37,1,222,203,34,61,127,211,40,82,199,79,34,64,60,11,54,1,210,241,15,0,124,2,112,134,180,70,217,78,209,156,19,95, +246,32,179,31,158,101,21,227,121,247,10,126,231,35,244,210,12,168,251,227,18,225,154,251,250,192,18,205,56,229,175,188,83,129,32,242,117,254,159,18,137,106,188,101,3,52,18,244,137,113,196,250,53,246,44,171,17,247,199,206,251,131,205,130,204,0,16,153, +57,254,33,128,115,52,3,74,114,64,141,230,26,217,101,7,178,155,160,57,10,233,3,247,34,82,68,158,93,154,193,223,17,193,43,17,169,58,122,239,111,153,237,143,83,17,89,208,58,230,5,222,6,152,151,227,31,56,231,62,3,184,203,200,184,65,191,245,166,163,58,250, +177,199,247,174,98,22,186,18,46,159,223,240,161,35,114,124,147,225,254,248,174,182,129,96,6,128,72,208,249,151,104,106,153,69,198,98,88,106,38,160,62,192,57,220,197,20,205,26,209,189,9,252,101,77,222,239,59,8,71,247,200,55,228,125,173,243,66,179,1,53, +8,102,0,136,36,12,240,103,141,106,138,204,69,49,208,76,192,190,142,213,167,67,30,39,36,119,159,223,50,218,115,143,124,210,61,50,200,124,143,20,186,71,152,13,32,1,32,34,119,252,3,29,146,50,166,52,30,225,210,57,183,79,135,250,7,79,239,119,157,82,61,86, +191,197,215,229,53,199,123,236,147,75,52,93,241,196,26,105,211,97,87,3,138,34,93,176,4,144,174,243,47,193,116,230,107,152,136,200,233,182,100,10,192,15,79,239,245,49,181,20,172,234,163,175,137,125,111,182,109,248,84,231,95,113,43,60,139,131,202,102,4, +51,0,132,127,99,91,129,233,204,109,80,237,144,9,240,53,136,231,62,69,99,171,223,116,239,233,113,195,45,247,9,157,255,235,56,180,108,70,144,0,16,30,157,255,37,252,14,96,201,133,4,148,158,222,39,229,84,244,196,211,115,202,45,247,9,157,218,246,216,183,108, +70,144,0,16,30,28,255,128,70,173,87,18,224,139,0,76,73,0,250,37,0,220,39,189,147,101,34,18,176,7,32,17,231,143,38,229,63,164,52,14,115,80,207,245,4,56,231,156,135,231,207,69,100,152,184,174,206,0,252,209,243,99,150,34,242,134,206,191,55,204,208,244,169, +112,140,48,51,0,4,157,127,82,17,206,197,19,50,246,37,219,105,6,50,246,241,141,131,167,46,188,161,243,239,12,67,52,125,1,236,49,34,1,32,2,227,156,206,191,83,124,122,162,225,169,240,244,236,58,147,232,209,7,138,13,231,95,209,249,119,78,2,206,41,6,18,0, +34,92,244,207,136,166,31,92,110,68,253,190,8,214,44,3,217,250,34,57,229,218,62,41,193,198,216,62,192,158,0,18,0,34,144,243,191,160,243,239,21,235,119,7,248,32,0,243,28,106,170,250,141,115,95,25,0,93,195,111,84,231,94,73,0,135,40,145,0,16,30,157,255,8, +192,39,74,162,87,12,52,19,48,128,159,121,10,117,70,178,245,241,173,133,174,221,37,56,15,163,111,124,234,250,42,102,194,15,126,163,8,162,115,254,67,196,151,206,188,71,115,201,8,208,164,185,151,26,85,15,52,82,123,107,244,189,219,232,209,199,8,224,89,70, +106,188,240,240,140,15,186,118,195,8,246,197,82,215,127,176,246,190,150,247,197,83,184,116,206,205,120,165,48,9,0,209,159,243,143,37,162,185,215,40,175,6,80,191,102,20,244,187,70,250,115,108,236,91,202,132,156,162,21,204,18,91,187,93,112,141,230,36,196, +244,181,146,143,158,100,40,215,126,44,19,130,1,128,111,206,57,30,15,140,8,156,3,16,23,1,184,128,237,212,255,21,154,179,244,245,129,36,103,132,102,34,222,239,25,45,239,155,92,12,167,231,123,21,44,96,5,224,108,27,167,255,138,220,74,52,125,63,39,134,191, +245,171,136,156,209,90,147,0,16,221,26,205,18,254,46,83,217,53,218,191,80,199,191,236,240,123,7,106,52,207,50,32,2,43,17,25,100,166,207,46,131,207,92,233,222,184,232,97,111,84,186,55,44,102,5,222,139,72,78,37,45,18,0,162,119,131,121,7,91,245,204,149, +26,182,177,135,104,241,194,120,212,115,40,110,69,164,204,76,159,107,248,187,94,57,4,174,0,156,245,153,213,49,76,146,107,17,249,72,171,109,31,60,5,16,135,177,60,51,228,252,87,0,190,0,40,250,118,254,64,115,108,76,68,42,0,167,250,236,20,145,99,205,52,213, +111,94,1,56,21,145,170,239,146,142,238,141,49,154,134,193,47,134,246,71,201,219,3,73,0,136,238,88,254,103,67,81,77,33,34,99,223,245,106,17,153,160,105,132,186,79,112,153,115,76,151,166,248,205,115,0,165,234,170,207,189,177,78,4,174,140,200,226,156,163, +130,73,0,136,195,113,134,240,93,255,247,104,46,255,168,66,54,170,105,93,113,136,166,147,154,32,44,225,90,157,255,44,224,254,104,179,101,31,13,16,229,182,60,65,144,0,16,7,32,116,215,255,87,17,41,14,233,236,239,193,200,141,12,69,58,93,96,145,161,94,167, +84,2,184,18,145,145,149,83,28,186,87,135,0,190,102,110,187,8,18,128,120,161,117,180,80,209,255,74,163,126,147,44,94,35,157,84,72,64,142,4,32,149,18,192,149,234,162,181,253,177,212,189,251,17,225,122,3,6,236,5,32,1,32,246,71,168,218,255,28,77,173,191, +182,44,156,196,72,0,65,231,223,103,54,96,30,232,21,62,83,77,72,0,136,221,163,255,17,252,93,67,251,200,168,161,169,101,70,145,162,77,132,4,112,114,26,157,127,159,123,100,129,166,129,54,196,62,41,120,79,0,9,0,177,59,66,108,154,171,208,141,126,123,226,44, +96,132,211,133,129,230,41,128,184,48,71,100,13,110,107,13,130,33,72,0,9,128,85,189,160,8,204,102,0,126,192,111,253,63,154,136,230,25,121,13,208,212,210,163,155,26,40,34,146,169,142,199,56,13,240,30,192,48,230,177,205,206,185,9,252,14,214,90,138,200,27, +90,117,102,0,136,237,54,232,200,179,243,191,141,217,249,183,17,14,154,52,231,138,26,68,244,132,21,128,81,236,119,54,232,94,247,153,49,27,176,12,64,2,64,108,15,159,155,229,30,137,164,232,52,149,94,81,125,136,158,80,37,84,174,41,225,119,86,64,73,245,33, +1,32,182,131,207,25,233,85,74,183,208,137,200,20,205,88,84,130,232,18,95,84,183,82,217,39,75,207,100,249,152,42,100,80,15,40,2,91,208,59,192,191,123,122,92,178,87,119,58,231,102,0,254,136,196,24,179,7,192,54,230,34,50,76,116,13,124,94,49,158,205,149, +215,204,0,16,251,194,151,161,89,1,24,39,44,199,17,216,15,64,116,179,79,82,174,95,143,61,238,147,146,234,68,2,64,216,32,0,23,41,179,113,61,251,204,89,228,196,161,56,83,93,74,117,159,44,1,248,42,109,12,169,78,36,0,132,13,150,60,73,93,144,122,43,27,47,14, +34,246,197,181,239,155,253,2,102,1,72,0,72,0,8,3,240,113,142,125,158,114,84,179,129,10,105,94,33,76,244,139,123,100,114,162,68,109,129,143,99,129,111,169,86,36,0,68,120,150,60,205,69,152,154,226,100,41,192,24,34,184,43,254,44,179,134,53,31,54,129,25, +0,18,0,194,0,234,156,62,86,143,111,221,26,118,134,57,26,70,203,223,124,157,210,145,63,218,4,130,4,32,142,168,168,244,244,168,28,103,207,87,176,123,42,96,64,237,55,131,21,242,204,24,121,177,9,30,109,28,65,2,64,60,19,17,47,51,252,230,5,128,11,174,62,241, +10,46,50,234,143,201,218,38,16,36,0,57,226,54,215,15,23,145,49,108,54,4,178,4,96,3,115,213,145,92,49,7,65,2,64,16,9,163,50,248,78,57,150,0,44,126,115,238,205,162,204,2,144,0,16,68,210,89,128,26,97,238,68,39,1,176,253,205,87,170,27,4,65,2,64,16,9,99,108, +236,125,88,2,160,78,16,4,9,0,65,120,200,2,44,12,102,1,136,176,209,255,130,98,32,178,179,133,20,129,29,232,17,153,155,158,31,179,20,145,55,148,181,43,208,28,125,250,221,196,70,204,236,70,64,67,55,1,174,0,12,73,0,188,173,201,71,150,90,152,1,32,158,134, +143,179,184,60,115,14,123,199,2,35,152,140,215,53,249,178,130,11,58,127,175,251,142,206,159,4,128,120,102,115,120,233,194,229,48,142,7,227,15,59,195,129,114,234,3,176,66,0,86,224,108,8,218,4,18,0,34,51,48,11,0,239,87,161,146,0,216,251,214,41,7,224,208, +38,144,0,16,150,224,99,80,13,47,229,120,192,152,6,56,219,111,29,83,253,189,218,4,14,26,34,1,32,94,129,143,62,128,146,98,254,153,5,88,0,184,54,240,42,57,173,137,133,111,101,231,191,255,53,161,188,73,0,8,3,4,224,3,197,252,8,22,234,192,57,221,149,110,225, +91,39,84,123,239,54,97,70,49,147,0,16,6,54,9,155,126,30,101,1,106,132,191,35,161,200,225,36,128,126,99,17,248,53,110,217,141,30,196,22,144,0,144,0,16,175,96,225,233,57,35,138,218,92,68,152,67,111,198,144,107,109,14,190,108,193,130,162,38,1,32,94,142, +70,125,177,228,99,74,251,17,166,8,127,36,176,204,64,206,161,191,113,37,34,36,0,1,108,129,71,219,70,144,0,68,13,31,221,178,133,177,129,44,161,137,151,133,35,129,57,172,71,232,12,0,157,255,26,156,115,67,79,122,199,19,0,36,0,196,150,168,61,61,167,162,168, +31,33,116,51,224,31,25,200,56,116,3,32,9,192,99,248,74,255,215,20,53,9,0,97,107,179,156,80,212,143,178,0,179,192,145,10,123,0,122,142,66,153,134,14,102,3,72,0,72,0,8,99,155,165,224,105,0,91,89,128,148,215,195,192,183,113,236,239,175,235,81,120,34,215, +83,74,156,4,128,216,110,179,44,225,239,88,90,69,137,63,66,104,67,149,50,33,43,51,95,91,107,240,181,247,111,41,106,18,0,194,102,22,224,56,167,155,232,182,36,95,33,39,3,166,92,6,8,73,0,174,57,247,255,81,244,63,128,191,244,63,137,23,9,0,97,116,211,12,0, +156,81,220,102,12,86,202,83,26,67,54,57,78,168,214,143,224,115,207,215,20,183,209,128,135,34,48,205,210,151,0,126,247,240,168,133,136,188,163,196,31,69,71,11,79,178,127,10,239,82,155,83,175,199,205,238,2,61,126,37,34,204,114,61,94,143,239,240,83,255, +167,236,13,227,55,138,96,167,77,83,224,233,99,76,171,158,186,139,39,0,62,121,248,180,194,57,87,113,64,138,178,98,145,165,115,110,138,112,167,36,202,4,35,214,144,165,13,166,160,31,219,177,10,254,102,78,76,122,250,134,225,51,4,253,158,151,60,145,0,28,162, +88,31,212,88,173,255,108,243,231,214,255,113,166,17,228,76,127,238,247,36,8,190,8,0,244,57,36,0,143,157,70,40,2,144,98,31,64,73,2,96,6,159,61,62,107,47,155,162,14,254,237,154,13,46,14,176,197,63,127,68,132,13,137,235,193,14,29,190,59,86,227,84,122,48, +188,51,52,245,176,90,68,174,183,124,191,5,252,13,79,249,200,75,82,30,201,222,87,9,230,23,61,17,145,247,137,201,210,87,202,121,19,76,65,255,26,253,95,122,122,220,92,68,182,117,218,33,236,240,53,237,93,158,155,160,112,206,157,59,231,190,187,176,184,113, +206,125,82,182,251,220,187,158,249,124,31,106,199,35,217,79,2,234,70,145,216,126,11,133,9,53,249,49,17,243,40,251,179,151,34,124,181,125,55,129,109,240,119,245,5,5,181,35,109,197,31,168,194,221,57,155,248,161,138,56,12,108,60,75,106,203,79,217,143,2, +234,67,149,82,212,25,80,142,188,245,50,220,58,20,79,56,253,115,181,117,22,113,167,62,130,25,163,196,20,255,196,64,180,191,143,34,22,250,254,83,102,1,130,145,70,70,174,17,103,82,168,197,193,162,255,233,90,0,99,57,240,122,46,43,144,197,152,116,73,92,225, +75,52,245,174,152,211,59,109,3,147,207,72,230,148,39,2,126,234,208,20,97,174,78,78,230,104,102,192,250,255,181,136,48,3,0,239,181,255,80,118,171,243,61,168,182,176,38,1,136,75,217,135,0,206,145,199,253,234,116,62,105,25,206,117,68,63,15,64,179,88,223, +3,61,158,68,54,60,9,75,1,53,128,191,82,188,72,234,40,65,69,255,132,102,224,8,157,255,254,40,156,115,99,138,225,81,36,19,2,41,232,112,153,233,218,89,178,137,99,58,255,131,117,248,78,125,11,9,128,81,37,31,56,231,190,129,55,126,117,5,54,195,224,231,221, +0,161,174,8,38,1,216,31,115,206,254,255,57,213,242,19,136,46,112,225,156,251,150,146,93,60,74,68,201,75,52,105,70,214,251,186,195,0,0,179,0,97,35,201,227,4,100,119,156,217,154,89,195,88,247,50,209,13,70,154,13,72,98,88,87,244,4,192,57,247,25,192,13,149, +188,183,44,64,73,49,4,115,38,131,152,13,141,190,251,32,179,53,179,22,24,49,250,239,30,133,146,128,207,177,127,200,81,228,10,126,201,40,181,119,156,231,46,0,109,254,89,5,122,124,204,4,44,84,70,110,149,98,195,22,247,174,57,140,213,7,145,0,4,114,254,21, +117,176,119,12,217,16,24,52,162,140,185,172,197,244,127,56,251,56,70,154,119,74,88,67,21,51,9,56,138,84,185,233,252,253,226,19,71,101,6,187,211,252,67,140,77,71,250,206,195,204,214,202,138,236,11,248,189,240,135,36,32,82,18,112,20,161,114,211,249,251, +199,0,225,206,194,231,158,1,0,226,44,3,148,153,174,149,5,124,163,201,34,9,72,142,0,208,249,135,53,232,57,151,2,2,31,7,140,177,12,16,234,157,179,62,254,199,212,63,73,64,146,4,64,21,155,206,63,44,62,103,126,42,160,14,244,220,15,17,202,234,67,102,107,100, +193,70,150,96,234,223,2,9,136,38,80,58,138,68,177,43,42,182,25,92,102,60,32,40,148,115,41,98,58,14,168,239,90,144,0,120,149,57,203,116,182,2,165,40,178,118,71,17,40,118,59,215,159,176,129,34,99,67,19,210,185,196,84,6,168,66,61,88,68,114,173,255,199,126, +233,89,138,129,146,121,210,110,154,0,40,171,253,6,14,249,177,134,81,74,247,213,239,224,92,66,246,1,196,52,21,48,84,250,255,54,211,232,191,2,167,160,90,195,0,17,100,75,173,103,0,190,145,213,146,225,26,67,168,8,115,24,195,81,76,125,71,30,255,243,39,239, +33,152,250,183,138,33,140,159,200,56,50,172,216,99,240,70,63,235,184,201,176,31,32,164,147,137,97,63,140,50,93,155,16,54,114,128,102,12,58,97,23,166,79,79,137,97,86,123,71,221,137,2,51,17,121,159,153,225,117,129,30,125,45,34,35,227,178,153,34,80,185, +66,68,36,51,61,188,3,143,252,197,130,247,22,199,83,91,205,0,48,165,21,15,134,177,207,195,222,3,161,106,205,199,150,51,46,250,110,199,153,173,73,40,89,95,210,249,71,5,147,54,242,55,131,138,61,54,174,216,115,0,155,131,70,62,100,174,220,149,115,238,86,68, +38,153,124,111,29,112,205,71,0,172,202,153,233,127,63,54,178,2,103,162,60,69,250,6,0,254,48,28,40,157,137,200,5,9,192,243,138,93,192,214,245,149,115,52,77,95,53,154,84,247,242,149,247,47,85,9,75,37,49,57,17,131,75,231,220,50,147,99,88,33,83,121,37,9, +64,190,4,64,207,151,231,152,113,155,233,26,47,69,164,126,69,70,235,54,120,100,136,20,124,118,206,77,69,100,97,69,176,98,76,185,111,16,190,209,105,165,78,255,162,139,154,141,146,130,145,254,188,77,124,163,46,1,124,76,253,42,86,53,48,63,66,201,88,68,222, +24,149,139,11,248,248,55,169,143,0,214,222,168,27,164,127,44,250,94,109,240,244,53,103,191,131,220,206,212,6,255,30,248,219,106,17,249,72,2,240,235,34,157,33,252,192,159,43,0,103,125,25,18,85,196,17,154,244,93,170,100,96,9,224,93,6,198,120,22,48,178, +248,211,90,166,69,35,211,80,71,158,230,34,50,76,92,223,10,52,141,209,169,58,255,123,52,153,173,105,95,1,132,202,112,12,224,36,240,183,158,90,41,151,30,25,81,238,1,194,142,250,189,215,200,181,234,211,113,137,200,76,68,198,34,82,0,248,168,132,35,53,12, +144,199,241,192,58,224,179,45,158,4,96,250,191,95,251,152,226,64,180,149,218,192,143,34,82,168,109,236,45,123,40,34,11,17,169,212,246,174,2,126,247,185,21,251,104,229,20,192,89,64,229,158,3,24,118,145,106,218,81,25,107,85,198,55,0,190,40,9,73,5,230,7, +96,116,128,144,101,14,139,83,1,67,190,83,157,184,174,125,67,90,29,255,247,106,243,10,13,186,188,219,94,52,3,230,66,77,245,28,168,207,35,1,8,220,248,119,37,34,195,144,233,106,17,89,174,101,5,78,3,42,101,215,40,19,63,30,24,210,233,12,44,93,54,162,239,18, +50,162,73,182,231,68,247,80,153,200,231,204,209,164,191,219,104,63,180,221,29,34,92,22,246,147,133,201,158,22,50,0,227,64,198,227,74,35,112,51,16,145,137,42,229,71,164,113,174,185,74,149,4,104,39,111,200,52,162,165,50,64,200,119,185,183,212,85,221,131, +243,175,18,248,148,91,52,105,254,161,181,163,194,234,3,66,144,128,129,250,190,124,225,156,43,92,24,76,34,145,79,233,156,171,93,252,184,72,84,127,167,1,101,250,195,144,28,126,4,148,195,52,81,221,186,72,96,223,215,122,10,138,123,249,121,4,205,2,132,206, +0,132,96,64,115,24,169,191,108,193,78,107,17,41,209,148,6,98,238,17,248,148,232,237,129,33,83,207,38,202,0,6,210,255,117,130,206,191,130,173,121,40,59,103,101,208,164,250,75,223,245,253,3,80,33,76,249,53,104,22,224,40,160,146,23,240,127,28,99,5,96,20, +219,17,53,45,13,20,104,26,103,86,145,26,133,203,4,73,64,104,227,102,161,12,16,250,29,146,170,255,235,30,137,181,108,182,2,240,69,107,252,147,200,108,236,82,117,217,183,125,61,9,121,34,32,100,6,32,132,51,168,98,174,23,138,200,24,77,247,234,87,146,0,19, +235,17,154,0,88,56,13,112,156,249,26,208,249,55,248,138,166,171,127,28,241,126,94,4,242,75,193,50,210,33,9,128,239,20,215,215,20,198,212,106,247,234,25,154,70,193,24,79,12,164,150,9,8,185,6,65,203,0,6,210,255,169,156,152,137,217,249,207,209,52,248,157, +165,48,252,75,125,132,239,0,43,88,185,231,40,160,178,251,52,28,247,72,172,227,82,251,3,134,136,179,44,144,18,9,8,157,130,30,101,250,108,32,145,250,127,164,206,191,77,247,15,83,202,194,40,198,240,219,115,53,8,101,15,67,101,0,124,51,158,42,213,209,180, +154,114,27,34,190,99,131,151,58,26,57,118,132,54,126,199,153,62,219,2,249,234,194,249,151,17,58,255,91,52,195,211,146,10,170,214,108,234,18,254,75,1,65,198,19,31,5,80,248,33,252,78,181,186,78,144,161,110,42,236,66,79,11,124,137,236,213,111,18,32,1,161, +157,80,144,50,64,128,44,94,114,4,64,117,63,182,137,153,95,180,187,127,145,184,77,173,1,92,123,124,100,25,226,72,96,136,12,128,79,102,181,66,70,247,102,43,35,255,136,120,142,12,14,98,39,1,70,110,62,28,101,242,76,139,178,63,196,249,199,116,179,223,61,128, +247,169,70,253,47,248,42,159,229,85,239,205,128,33,8,128,207,180,225,69,234,183,210,61,195,92,135,158,217,107,214,36,0,225,203,47,94,143,18,233,179,142,51,151,249,33,242,27,69,230,252,175,208,164,252,147,190,230,251,9,91,186,4,224,115,136,153,247,61, +117,228,89,241,135,104,142,177,249,138,254,47,144,33,244,164,192,8,205,0,161,88,72,192,93,196,141,129,185,101,1,70,148,249,222,54,176,66,92,55,251,157,246,125,75,170,113,92,120,204,2,20,190,3,33,223,25,0,159,134,227,34,99,165,109,137,192,4,192,123,196, +115,74,32,214,211,1,36,0,36,0,219,58,255,88,26,254,86,104,82,254,147,204,109,168,239,44,128,215,189,37,158,55,64,13,224,131,135,71,221,235,228,60,2,63,83,182,53,128,63,34,138,58,38,17,201,119,8,224,206,192,171,188,233,155,244,106,163,210,119,3,223,250, +62,166,148,116,100,206,127,14,160,204,61,128,218,176,159,51,0,111,61,60,238,86,27,186,211,202,0,168,16,63,120,122,220,5,213,246,49,139,13,124,245,101,210,153,0,67,142,200,135,204,70,148,121,210,206,63,248,21,233,153,103,1,62,248,252,54,159,37,128,210, +227,179,38,84,219,39,21,185,66,60,125,1,177,149,3,44,52,165,157,36,242,140,24,100,157,162,243,63,181,118,69,186,33,76,60,234,76,122,25,0,248,59,251,127,69,246,250,34,9,152,0,248,19,113,244,5,196,68,2,44,68,164,195,62,207,18,7,152,225,97,89,214,41,57, +255,21,128,63,115,175,247,111,145,5,240,149,65,37,1,96,244,223,171,50,79,85,201,98,33,1,231,17,188,231,194,200,123,244,121,150,216,10,25,51,79,0,156,115,151,17,57,255,50,133,123,82,18,242,45,222,72,182,79,2,224,163,1,237,62,245,169,127,29,146,128,25, +154,35,153,49,92,168,114,166,6,149,25,128,215,113,28,233,223,29,35,217,122,201,249,87,17,236,171,57,154,27,252,178,58,223,127,128,205,172,225,103,200,154,183,102,109,159,4,160,240,240,12,58,255,221,20,122,169,153,128,24,106,170,149,101,18,96,136,120, +22,125,212,16,117,120,77,65,89,39,227,252,175,193,78,127,171,62,198,219,62,59,242,180,41,134,9,45,78,114,36,64,143,157,196,112,66,160,114,206,125,243,57,245,110,143,136,202,132,156,122,248,59,71,148,241,139,54,110,224,156,251,22,137,243,191,18,145,17, +157,191,93,31,227,203,103,250,202,0,12,82,90,156,68,137,64,21,9,9,24,161,25,29,108,145,4,44,140,188,199,113,151,242,49,50,250,183,133,185,116,181,202,231,198,16,73,122,205,249,199,64,82,178,38,0,190,124,166,47,2,224,131,205,220,167,126,67,149,39,18,240, +53,130,87,29,26,37,1,86,156,211,160,99,103,52,130,157,209,181,166,246,248,154,243,143,225,46,139,47,116,254,7,219,200,5,252,244,1,20,204,0,68,108,24,34,86,240,51,196,49,43,96,8,224,187,177,75,132,106,67,239,114,98,244,239,74,70,198,170,123,223,35,113, +254,167,153,221,228,23,187,175,73,138,0,16,113,145,128,73,36,36,192,218,77,130,150,72,104,39,247,139,235,223,81,26,250,46,19,89,150,200,174,243,61,229,25,127,34,117,2,192,163,44,121,147,0,11,247,211,47,96,107,182,66,101,228,239,232,10,43,11,141,107,58, +224,135,206,63,95,36,227,107,82,34,0,236,104,205,155,4,124,51,50,53,208,146,113,56,49,242,119,36,35,219,181,233,126,116,254,249,34,25,95,147,18,1,24,80,47,179,38,1,128,141,169,129,150,8,192,65,51,1,244,207,22,36,0,63,229,113,142,120,166,251,209,249,211, +215,100,69,0,134,212,203,94,73,192,71,196,49,58,56,244,212,192,133,49,121,84,129,254,108,82,178,85,157,58,139,64,255,219,209,190,116,254,113,251,26,47,89,6,95,4,160,246,240,140,223,169,151,189,146,128,26,241,220,31,80,57,231,66,29,19,180,86,31,220,107, +38,128,254,153,19,99,223,226,93,182,58,224,231,14,113,12,248,105,157,63,251,161,226,247,53,94,214,144,25,0,98,23,18,48,139,136,4,148,104,154,3,139,0,68,201,18,246,157,9,48,50,168,127,94,101,171,186,19,203,25,127,58,127,250,154,172,9,0,44,116,130,103, +66,2,70,17,109,212,187,0,199,4,173,17,164,79,158,254,76,159,184,247,249,48,213,153,59,58,127,34,101,31,227,139,0,248,82,76,18,0,127,145,88,44,141,129,33,142,9,90,51,196,195,93,72,144,254,191,214,28,223,194,163,145,175,16,207,49,63,0,56,163,243,247,6, +95,118,36,157,18,128,158,221,245,193,224,143,169,159,222,72,192,36,50,18,224,243,152,160,69,99,188,203,183,91,108,118,171,61,57,255,79,136,231,152,31,192,110,127,223,240,225,99,238,125,205,187,240,89,2,240,97,20,7,70,206,130,147,4,216,196,165,167,19, +2,11,131,223,190,75,67,159,69,34,221,187,76,85,55,46,34,210,103,58,127,143,80,223,226,131,24,122,11,32,82,35,0,0,240,153,170,74,18,240,82,36,236,225,74,97,139,25,128,173,200,177,71,35,103,134,0,104,167,255,13,226,232,244,167,243,15,7,95,190,37,73,2,80, +123,122,78,193,44,0,73,192,43,104,175,20,46,50,34,0,219,102,1,78,140,234,88,47,246,99,173,211,191,164,243,39,94,33,198,133,167,199,213,222,246,149,71,1,14,0,252,240,244,184,37,128,119,22,230,134,103,184,73,46,35,122,229,37,128,143,125,52,80,57,231,150, +176,57,155,226,221,115,215,102,171,51,252,110,240,157,87,34,50,232,97,141,98,186,208,135,206,63,156,93,27,232,190,240,165,39,111,146,235,1,208,15,154,123,122,220,0,192,57,85,55,72,38,224,107,68,175,60,64,115,76,176,202,40,11,112,182,231,127,11,137,62, +8,90,133,230,152,95,76,206,255,43,157,127,16,156,123,212,147,185,207,192,213,247,28,0,159,202,91,113,46,64,16,18,112,6,224,42,178,215,238,227,14,129,24,203,0,39,70,223,185,83,89,70,52,211,127,29,87,186,183,8,191,209,255,8,126,123,67,188,18,60,223,4,96, +26,192,176,23,84,99,239,36,160,138,144,4,156,117,220,28,104,181,252,244,100,51,160,225,230,191,206,100,169,205,126,223,16,199,76,255,77,231,95,129,240,237,252,139,0,68,209,171,143,244,74,0,180,246,56,247,248,200,246,252,55,111,10,12,67,2,174,35,123,237, +46,155,3,107,195,223,121,18,81,244,223,137,44,215,234,253,177,101,5,233,252,195,56,255,1,128,111,158,73,241,252,185,254,156,84,50,0,128,231,20,7,154,137,102,151,84,233,32,168,60,19,190,174,244,229,238,144,107,116,21,11,195,223,88,174,147,28,253,125,105, +248,125,15,146,165,174,101,44,51,253,31,57,4,196,151,173,72,5,223,2,232,139,111,223,24,140,0,248,158,149,62,10,124,69,108,174,89,128,165,58,150,216,72,64,59,62,184,58,224,219,23,198,191,241,236,153,223,91,212,163,189,101,25,225,88,223,117,231,95,242, +36,83,144,232,255,50,0,33,94,133,32,0,191,133,112,10,206,185,41,252,167,28,43,231,28,68,228,148,42,238,125,189,75,141,226,98,187,178,249,210,57,247,225,0,157,153,3,248,35,224,251,47,241,80,63,95,255,61,0,252,235,141,223,215,234,36,7,107,36,200,130,211, +220,155,60,170,33,175,34,220,54,247,116,254,65,157,127,8,157,153,134,88,111,9,36,228,2,225,206,27,79,72,2,130,172,249,80,157,204,239,17,190,254,12,205,188,128,229,142,223,60,69,255,99,117,151,74,174,90,7,127,255,140,211,223,36,0,0,240,95,244,215,127, +243,132,211,223,252,253,219,181,127,87,120,36,7,215,34,50,218,81,238,3,196,153,242,111,35,65,222,236,151,151,243,7,94,152,207,145,84,6,64,163,194,133,115,238,22,192,135,0,143,103,38,32,204,154,207,52,19,16,35,9,24,2,248,238,156,219,117,104,208,172,99, +2,208,58,251,197,154,163,223,36,0,11,236,222,53,255,79,175,252,247,117,167,191,249,251,183,250,207,125,145,130,157,28,97,164,195,125,232,252,195,58,254,118,110,76,40,231,127,27,170,100,40,1,133,30,50,11,176,119,84,71,28,188,238,35,52,13,54,177,98,235, +73,108,29,76,70,220,116,248,139,141,159,208,186,59,88,115,254,237,79,215,132,192,167,188,67,227,79,17,153,210,74,120,119,254,161,179,69,239,178,35,0,42,252,9,194,30,63,154,169,129,33,227,246,187,238,177,27,234,11,17,249,107,139,239,44,213,184,236,235, +244,231,170,163,86,28,254,46,132,96,136,166,255,225,80,50,240,113,155,123,0,34,174,247,239,76,116,136,206,236,80,123,66,44,164,243,15,122,204,51,52,1,40,212,192,133,76,9,47,117,243,145,121,251,93,251,11,0,159,34,254,132,90,35,182,229,43,209,197,143,45, +117,48,86,167,223,55,25,120,179,133,140,99,173,247,183,248,34,34,99,90,5,175,246,103,164,206,63,100,169,104,5,96,24,242,196,144,24,88,136,49,108,92,225,59,22,145,47,220,26,94,215,126,2,219,3,104,182,113,220,47,246,5,56,231,220,43,127,126,6,224,54,17, +167,191,45,25,248,160,191,190,106,124,69,68,94,137,224,98,173,247,155,136,0,51,181,59,231,176,113,244,53,56,241,19,35,11,50,67,216,227,82,91,71,117,68,231,107,95,35,76,51,104,151,120,54,125,251,204,247,45,84,215,218,104,127,150,160,211,127,137,12,12, +215,178,2,37,158,191,102,245,86,68,202,103,228,90,33,254,1,95,207,126,31,209,139,173,41,84,103,44,200,124,46,34,193,179,86,86,8,192,16,205,205,92,86,162,58,150,4,252,173,253,64,157,225,31,145,127,202,147,199,75,55,142,2,182,142,255,86,127,93,100,190, +252,133,26,227,15,207,16,129,39,143,0,38,80,239,7,56,232,199,183,157,177,144,242,95,199,123,11,189,103,98,104,129,198,176,81,10,104,49,85,34,192,13,234,135,153,135,238,5,233,2,51,52,25,164,197,134,94,159,208,241,239,69,4,30,165,72,85,79,66,140,104,237, +26,43,0,5,109,139,183,0,227,18,182,238,128,48,211,243,33,198,22,203,74,41,128,217,0,255,107,31,243,160,160,77,157,249,179,237,92,119,206,253,3,128,191,167,227,223,139,8,124,105,75,43,122,162,194,247,229,44,125,57,127,158,245,207,51,234,7,140,164,254, +173,18,0,171,145,224,20,192,95,17,204,119,143,125,195,86,72,227,226,166,5,128,51,17,185,118,206,253,75,0,255,47,87,119,47,34,240,127,137,200,127,113,206,125,6,48,78,228,219,120,214,223,143,31,57,135,189,155,31,205,101,126,142,44,73,71,29,172,197,235, +58,71,104,110,136,251,204,237,213,235,250,79,0,252,21,241,39,44,53,210,255,10,96,174,7,0,232,252,247,35,80,19,0,255,183,115,238,191,87,50,144,66,186,156,217,196,254,157,255,103,52,253,100,22,253,136,185,158,15,49,186,136,103,202,224,44,98,166,217,128, +154,219,173,183,245,159,32,190,227,129,11,52,153,162,107,228,213,213,223,55,218,83,3,199,106,212,139,72,191,131,199,253,250,181,25,165,250,12,171,253,33,38,7,61,137,225,5,181,238,4,38,104,106,148,11,110,191,94,214,191,70,28,199,3,219,179,252,215,74,0, +168,15,253,160,80,2,112,140,45,103,8,24,194,206,23,26,17,91,219,137,2,77,243,184,101,114,101,150,252,137,241,197,141,33,18,36,17,232,103,237,99,56,30,200,168,159,217,128,215,192,227,126,249,58,126,211,206,223,60,1,208,133,182,118,50,224,185,40,240,2, +192,87,110,244,206,55,185,213,227,129,51,0,87,140,250,131,102,186,78,61,170,0,0,32,0,73,68,65,84,3,78,96,251,72,96,240,81,175,137,6,6,159,208,76,242,179,158,5,50,63,232,73,34,89,112,235,145,224,58,17,152,50,35,208,233,250,91,26,18,213,174,113,173,206, +191,102,212,31,52,27,80,42,9,40,141,58,131,247,60,238,215,121,196,63,66,28,229,159,40,50,63,18,201,226,199,56,45,110,170,25,129,154,219,247,224,245,175,96,227,120,224,66,215,245,10,59,222,83,79,244,134,161,146,0,107,37,1,222,238,215,205,222,47,53,226, +143,169,135,34,154,178,143,68,164,8,177,142,140,173,209,244,9,92,179,60,112,208,250,135,190,61,112,161,235,120,5,166,252,173,161,80,18,80,25,33,1,95,69,228,140,203,114,144,173,63,214,245,44,35,123,253,168,122,62,36,66,197,152,224,97,182,122,76,88,174, +101,5,24,61,238,183,254,211,64,107,207,122,127,28,36,192,66,95,0,59,254,247,223,223,195,181,104,63,198,137,143,87,104,6,128,69,19,232,73,164,138,50,65,220,215,200,206,208,52,13,50,43,176,59,1,172,225,55,11,52,67,51,216,103,10,214,251,173,99,160,206,227, +83,32,18,192,142,255,253,163,253,51,196,125,199,67,148,115,30,36,98,197,9,157,18,238,10,83,253,33,25,216,110,221,11,248,57,25,176,220,136,252,185,54,113,145,128,54,19,224,43,146,100,199,255,238,78,127,132,184,106,251,207,33,218,146,143,68,174,72,149, +70,210,191,39,160,68,109,137,96,42,34,215,52,19,47,174,123,9,224,198,195,90,180,205,126,116,254,241,145,128,245,230,64,31,36,224,35,27,126,95,221,183,235,78,127,144,192,39,173,208,164,252,39,177,126,128,36,160,84,169,220,34,247,36,25,64,115,150,148,14, +232,105,242,119,217,163,236,191,130,157,254,177,195,87,77,153,29,255,207,71,250,31,18,115,250,235,206,63,250,91,29,37,33,69,171,17,223,9,129,109,193,50,193,211,235,62,65,183,189,32,116,254,36,1,187,130,51,254,31,239,201,98,195,233,167,136,100,122,61, +98,109,2,28,2,120,171,155,187,173,243,149,153,236,177,217,26,25,200,222,73,117,60,41,178,6,240,69,127,37,210,65,137,102,136,76,215,54,194,212,221,238,129,237,113,155,222,207,69,30,53,154,19,65,11,181,201,247,49,218,227,88,38,1,254,161,155,183,204,200, +209,239,18,177,214,104,74,5,139,12,141,207,64,55,225,161,37,32,118,251,167,139,62,78,7,152,187,219,221,243,158,59,86,91,156,90,106,191,11,98,208,254,204,57,9,112,127,70,217,142,248,28,82,167,118,114,98,245,26,33,200,194,56,117,48,46,152,206,159,36,96, +87,231,95,230,146,129,91,171,229,151,180,201,123,219,228,43,139,250,34,134,148,44,181,14,81,43,202,55,5,80,139,200,109,226,70,170,194,126,77,129,11,117,254,19,58,255,44,72,64,165,36,160,56,224,239,73,190,233,207,57,247,97,45,194,167,195,239,6,11,37,3, +102,78,122,73,96,37,43,116,51,86,116,250,94,208,102,7,102,41,102,8,246,152,13,177,0,199,251,230,134,2,135,141,13,78,110,204,239,90,132,63,4,203,172,62,201,64,59,25,54,152,237,145,64,10,215,110,64,42,90,248,12,193,58,33,136,222,9,58,231,106,53,102,175, +97,169,206,255,43,157,127,150,36,96,159,192,195,252,245,174,59,4,94,235,14,159,17,126,248,192,108,34,34,87,73,19,0,117,252,99,216,186,181,139,120,204,74,103,45,49,136,177,108,176,67,83,224,20,77,199,63,143,251,229,137,33,30,174,151,221,6,247,104,38,253, +45,35,220,19,31,214,28,253,144,246,215,180,253,29,251,36,2,226,73,1,233,248,211,200,18,204,99,104,124,218,162,41,112,166,206,127,202,229,205,26,35,37,1,219,68,192,239,35,210,253,63,24,221,147,8,4,39,0,58,178,245,156,74,152,28,234,181,76,129,73,82,240, +66,83,224,2,108,250,35,26,108,219,20,104,178,233,111,195,217,183,14,159,72,43,248,250,171,207,17,211,210,147,98,14,212,241,87,92,195,236,72,193,2,192,204,66,249,224,137,73,129,172,251,19,155,40,240,114,63,128,137,73,127,154,198,111,211,247,116,246,121, +97,162,68,160,243,128,69,122,80,212,145,70,94,236,234,39,126,18,2,37,8,247,190,27,13,55,38,5,214,224,164,63,226,87,148,120,122,82,160,247,73,127,218,160,247,22,15,233,251,214,225,19,121,99,137,38,19,213,105,217,82,58,86,222,115,52,247,58,19,196,75,138, +60,219,32,7,189,77,204,90,187,62,248,7,152,250,39,158,198,83,165,128,94,175,247,93,155,112,186,238,228,125,94,95,76,196,137,11,17,249,203,20,1,208,90,212,37,153,42,97,145,24,56,231,254,1,192,255,0,166,254,137,231,81,224,113,41,160,147,235,125,233,232, +137,30,48,3,240,103,23,228,84,58,80,240,33,154,187,217,169,208,68,223,196,96,137,61,75,9,154,9,160,243,39,94,66,137,166,20,112,43,34,227,61,244,171,77,221,15,232,232,9,15,118,241,227,161,13,216,7,17,0,237,180,62,167,146,19,1,153,112,75,10,22,250,243, +108,214,192,57,151,157,128,68,14,227,248,153,201,108,0,224,223,138,200,127,124,37,154,47,244,103,221,217,19,68,8,18,240,215,33,39,84,228,0,195,80,97,191,217,235,4,225,3,53,30,186,254,255,79,0,255,76,135,127,56,50,32,4,255,2,192,59,0,255,45,30,82,246, +57,93,55,78,196,135,189,143,169,254,70,231,79,36,138,82,51,2,111,82,119,254,125,59,253,231,158,149,40,25,248,255,0,252,119,104,74,1,5,183,17,17,1,46,157,115,216,135,4,28,237,225,252,71,116,254,68,68,89,128,58,101,199,239,211,249,91,123,62,245,134,32, +30,145,128,209,174,127,104,39,2,176,214,237,79,16,214,177,0,112,139,4,27,255,172,57,222,4,137,64,178,186,67,36,79,2,118,234,71,217,154,0,176,219,159,96,20,71,71,155,17,17,96,22,128,136,13,3,0,55,187,144,128,93,50,0,156,238,71,48,130,11,232,92,249,174, +212,33,130,216,130,4,108,157,165,223,138,0,56,231,46,192,163,46,4,163,55,70,213,121,101,3,152,5,32,98,196,208,57,55,238,132,0,232,141,126,159,40,83,130,145,27,35,233,204,190,129,89,0,34,86,124,86,223,189,63,1,208,193,23,223,40,75,130,81,27,29,103,166, +223,194,44,0,17,43,46,213,135,63,139,215,230,0,140,17,103,221,127,133,135,41,113,237,168,196,245,223,99,151,57,223,27,76,170,29,12,178,62,1,236,3,117,205,4,150,0,230,49,71,108,137,30,171,251,249,93,17,206,14,88,168,78,45,193,30,40,107,104,175,28,111, +109,253,35,123,191,203,152,92,109,156,27,108,216,248,245,223,199,104,227,11,52,151,243,141,159,221,151,47,8,164,0,240,61,130,143,156,227,215,187,232,189,223,246,166,76,107,125,254,119,169,11,240,150,251,212,107,180,22,237,117,191,169,58,255,39,246,74, +108,175,92,226,233,235,130,137,254,113,175,118,189,94,115,240,161,109,124,129,135,235,154,255,136,64,134,239,158,187,59,229,37,2,240,13,192,200,224,199,204,1,76,91,167,31,66,17,246,84,154,150,16,196,162,52,49,70,255,95,1,92,32,194,235,126,115,113,254, +145,146,128,129,70,82,159,152,5,232,221,182,207,214,28,126,76,246,125,164,63,22,3,190,43,17,169,182,38,0,154,242,190,49,198,2,47,0,76,251,186,159,59,128,226,148,107,44,178,4,240,59,247,255,65,152,105,244,63,165,243,39,9,232,1,35,205,2,240,52,84,55,88, +225,33,115,91,119,113,245,178,17,157,110,237,121,101,44,208,123,242,122,235,231,8,192,13,108,164,187,174,1,92,164,162,28,175,40,78,161,50,111,127,88,58,216,13,83,37,0,179,216,94,156,4,32,10,12,149,0,140,184,213,246,14,226,166,107,14,127,145,129,126,151, +104,50,71,199,6,94,167,22,145,143,175,18,0,35,181,255,43,0,227,28,148,132,132,160,19,68,155,254,207,213,249,71,72,2,88,6,216,221,225,215,237,15,109,57,198,0,78,2,191,202,47,189,0,79,17,128,73,192,23,189,7,80,229,16,241,31,72,8,70,96,201,96,29,81,166, +255,115,119,254,17,146,0,150,1,158,199,10,15,189,89,89,59,252,87,50,2,23,8,87,26,248,42,34,103,207,18,0,109,104,248,30,136,225,126,17,145,49,213,100,107,101,106,27,79,74,240,24,98,116,233,127,58,255,40,73,0,203,0,143,113,219,58,253,93,142,220,81,215, +221,88,245,200,55,150,154,5,248,153,37,253,237,9,134,235,219,249,175,0,156,237,115,151,113,206,208,13,55,91,35,110,229,26,33,200,169,92,16,253,217,127,34,26,44,84,215,74,228,89,6,104,211,250,173,211,95,82,37,246,178,221,99,231,220,12,192,4,126,51,185, +3,245,17,147,231,50,0,181,231,104,114,5,160,36,123,236,45,59,48,66,250,71,14,163,75,255,51,250,143,58,11,144,91,25,160,61,118,61,165,157,238,197,78,215,158,73,192,173,136,148,191,16,0,141,34,127,208,249,39,167,100,197,90,118,224,56,193,79,140,42,253, +79,231,31,61,9,200,161,12,112,189,22,229,47,168,149,201,145,128,55,109,246,230,104,131,217,250,196,25,157,191,23,135,179,16,145,137,136,140,0,188,1,112,138,230,148,197,42,145,79,108,39,133,17,132,15,44,84,231,82,194,74,109,194,169,58,135,145,218,12,238, +171,254,237,243,12,254,143,220,255,244,245,161,8,192,87,214,252,131,40,219,82,55,118,37,34,3,0,127,70,78,6,150,106,144,151,145,200,159,74,24,191,140,162,210,185,45,156,254,159,34,50,80,155,48,97,93,63,24,9,248,226,241,145,63,9,199,122,9,224,7,252,52, +182,220,3,24,82,209,108,193,57,215,246,12,196,116,196,48,170,250,63,9,192,214,186,104,253,21,99,237,3,104,143,234,77,69,100,74,77,51,167,247,11,248,105,224,94,138,200,155,159,25,128,141,155,144,250,70,69,231,111,210,57,77,35,204,12,44,16,73,250,159,206, +63,41,89,69,163,119,207,68,250,116,254,54,49,246,244,156,129,250,252,159,37,128,210,211,131,231,28,242,67,50,208,33,88,255,39,66,17,0,203,125,0,116,250,113,218,221,137,71,189,122,68,0,124,165,178,46,184,204,209,147,129,107,67,175,215,222,1,206,136,150, +89,0,234,29,157,62,179,0,123,18,0,31,103,197,87,108,252,75,130,12,172,159,38,8,73,6,162,112,254,68,178,176,162,127,215,120,232,222,167,211,143,31,190,214,207,123,6,128,138,153,14,17,88,110,28,45,252,11,205,192,16,159,88,128,233,127,34,28,66,234,223,92, +247,220,250,145,61,146,225,68,108,171,167,192,234,3,0,28,233,5,5,41,49,27,194,63,25,184,16,145,33,128,119,104,110,229,243,81,199,98,250,63,125,221,98,6,224,1,247,186,183,222,137,200,80,247,28,157,62,179,0,123,195,57,55,60,242,248,81,53,215,53,121,131, +189,16,145,51,17,41,0,124,68,191,205,131,44,1,16,169,19,128,182,153,239,163,136,20,186,183,22,20,125,242,240,229,43,7,191,193,79,250,255,158,108,53,59,50,80,3,168,117,196,244,8,64,133,110,239,153,224,9,0,34,36,22,232,47,211,117,139,230,194,150,41,237, +102,158,129,148,115,110,133,254,231,177,12,143,224,231,252,63,163,255,124,149,185,237,23,40,209,148,8,190,116,100,56,153,1,32,82,202,0,220,235,222,120,39,34,37,235,250,217,195,199,152,252,193,17,128,194,19,91,38,72,6,22,34,50,222,40,17,164,252,189,92, +116,202,240,37,108,166,248,199,76,241,19,30,9,64,65,2,64,132,50,236,181,136,84,120,56,82,184,203,41,2,70,255,68,204,89,128,185,234,124,161,71,247,106,138,146,120,66,183,188,16,0,31,32,1,32,158,35,2,109,137,96,8,224,61,154,78,231,213,22,155,131,4,128, +136,137,0,172,84,183,223,107,23,63,83,252,68,232,12,0,142,40,103,194,16,25,152,105,167,243,64,35,164,91,74,133,136,28,183,0,78,117,58,31,175,64,39,44,101,0,112,4,63,83,0,9,98,87,50,176,222,56,184,153,21,96,6,128,176,156,1,104,163,253,159,13,125,20,21, +97,16,191,123,57,5,192,26,23,113,128,238,44,158,200,10,144,0,16,22,9,192,102,180,191,160,136,8,195,24,138,243,112,249,182,176,29,154,232,16,206,185,191,5,240,55,0,254,209,56,121,225,98,117,179,222,86,95,173,4,240,239,85,15,47,232,240,137,142,245,190, +127,223,76,2,64,208,57,144,0,112,141,247,194,223,138,200,63,113,133,136,88,9,0,155,0,9,130,32,8,34,67,144,0,16,49,50,227,191,117,206,253,189,229,232,159,200,2,255,198,57,247,31,157,115,231,206,185,130,226,32,72,0,158,54,216,220,28,68,23,122,116,226,156, +187,1,240,31,0,252,29,37,66,24,192,223,0,56,3,240,221,57,119,227,156,59,161,72,136,14,108,93,233,139,0,248,184,186,149,4,128,216,155,60,106,132,245,3,205,5,41,37,165,66,24,69,9,96,226,156,251,193,172,0,17,1,230,71,224,148,62,194,118,180,255,93,35,172, +1,165,66,68,130,1,179,2,68,4,88,178,7,128,176,228,244,135,91,70,251,3,18,2,194,136,163,127,77,15,55,179,2,67,138,141,216,82,183,122,135,47,2,80,114,61,137,103,156,254,64,163,253,59,0,119,91,70,251,36,0,68,44,4,96,51,43,112,231,156,187,83,157,167,14,19, +207,193,11,81,244,85,2,160,162,19,155,142,191,116,206,93,2,104,163,125,70,70,68,78,198,125,2,224,135,115,238,210,87,195,23,193,12,192,6,22,191,121,34,0,52,238,68,123,26,228,4,64,133,195,26,67,163,200,0,56,231,56,12,168,3,25,38,146,1,120,14,21,128,202, +57,183,80,82,112,197,137,130,132,39,159,185,56,130,159,153,234,188,112,40,95,3,62,216,104,232,27,227,240,83,33,44,1,16,169,16,128,22,133,238,141,159,141,131,44,17,100,13,31,62,115,249,27,252,220,59,60,112,206,21,100,182,89,57,254,82,163,253,17,157,53, +65,236,132,82,127,150,206,185,41,128,169,136,92,83,44,217,216,206,194,147,205,156,29,121,86,106,34,113,197,213,78,231,239,0,110,208,164,55,251,82,100,102,1,136,84,162,255,151,158,81,1,152,58,231,190,115,182,64,86,4,208,7,150,71,30,175,234,37,1,72,211, +233,15,156,115,159,180,139,191,61,179,239,195,72,189,69,4,3,166,56,174,56,89,217,21,170,131,62,159,215,206,22,184,211,61,71,50,144,38,70,62,30,34,34,63,51,0,115,15,207,59,102,77,43,41,167,127,226,156,251,134,166,139,255,2,254,27,61,153,1,32,82,207,0, +60,135,161,238,185,239,206,185,111,236,23,72,203,182,2,56,246,240,168,91,224,97,14,64,237,105,195,140,184,196,81,43,231,241,154,211,159,4,94,79,18,0,2,212,63,140,240,112,164,240,155,115,238,152,75,195,232,127,11,204,214,9,192,204,211,67,63,115,125,163, +116,250,151,58,157,111,106,136,196,21,136,228,142,9,150,1,146,148,153,69,253,27,161,233,23,104,231,11,144,12,196,7,95,62,50,8,1,40,156,115,21,215,56,58,167,95,25,140,182,153,1,32,168,127,207,191,91,69,50,16,157,221,173,60,146,202,25,0,200,218,195,151, +0,126,247,240,224,133,136,188,227,114,219,115,250,26,65,196,116,108,239,43,154,179,211,203,24,94,150,67,129,146,137,254,7,170,119,159,34,19,237,82,9,61,143,21,218,212,251,239,158,8,192,74,68,6,235,25,0,168,98,248,202,2,140,185,220,140,244,59,64,20,39, +1,136,228,80,192,239,9,0,102,6,210,183,197,99,143,182,236,167,175,95,39,0,181,199,239,253,204,91,177,130,40,89,219,189,31,179,211,223,52,196,69,68,242,167,18,166,33,163,168,244,110,75,50,192,211,4,225,116,190,132,223,254,184,159,190,126,189,4,48,64,211, +221,237,11,75,0,31,69,100,70,21,232,85,185,10,0,31,240,144,222,79,9,75,0,95,208,28,137,138,2,44,3,36,65,0,206,212,96,167,234,44,167,250,115,203,233,173,189,235,251,16,205,208,52,159,186,244,70,68,150,0,240,219,154,97,90,58,231,110,213,89,248,98,160,55, +206,57,146,128,126,148,170,173,233,167,156,105,25,104,36,54,64,36,125,0,188,32,40,122,231,191,174,115,169,226,103,176,224,156,155,41,25,184,166,157,78,194,249,223,182,206,31,120,92,2,0,154,243,164,190,55,211,141,115,142,243,1,14,83,164,193,90,61,255, +59,128,59,52,77,74,57,148,89,162,235,3,96,41,32,106,153,20,136,179,254,191,47,134,106,75,238,116,28,241,165,218,26,150,10,14,211,247,81,0,231,255,139,143,151,77,71,130,230,122,224,223,3,200,100,44,34,95,168,26,59,71,249,37,242,30,179,60,67,83,6,152,198, +244,210,204,2,68,75,0,70,104,210,255,236,97,106,106,201,53,179,3,59,235,250,103,37,85,190,177,2,80,60,155,1,208,255,16,202,144,142,117,198,117,73,21,121,82,105,138,141,6,190,54,202,207,93,94,133,26,227,65,100,235,73,165,142,79,22,3,213,181,130,171,6, +168,237,105,179,3,237,169,130,19,222,81,240,172,158,151,122,103,202,56,208,43,76,214,157,255,47,25,128,214,209,160,185,212,37,36,38,0,190,228,220,128,178,214,188,215,70,248,220,84,207,99,170,89,128,232,162,144,220,51,1,145,17,161,161,70,255,44,89,190, +142,197,90,134,224,150,182,28,159,209,156,186,8,137,119,155,235,32,207,188,112,13,127,205,128,175,25,246,175,30,111,44,12,169,36,67,0,127,208,225,239,133,40,203,0,185,147,128,8,179,32,76,255,147,16,236,20,241,163,25,22,101,129,48,222,138,72,249,139,237, +121,225,197,111,140,25,248,137,126,196,44,17,229,104,163,251,161,254,202,166,154,253,177,68,51,21,240,2,145,156,6,32,1,136,142,0,12,208,28,255,251,196,189,218,217,158,173,213,182,215,34,114,155,80,32,247,65,163,125,75,68,241,227,83,129,180,188,240,33, +83,248,185,150,112,31,38,217,158,83,157,111,214,52,12,42,196,96,45,178,111,235,135,140,32,186,71,180,101,128,28,73,64,132,209,63,211,255,126,2,189,217,90,182,32,38,251,222,30,157,44,12,190,230,149,136,84,79,218,157,23,62,172,64,248,94,128,93,148,166, +86,197,9,162,52,42,175,183,120,104,72,43,145,198,196,176,152,140,71,180,101,128,156,72,64,164,13,144,76,255,135,11,248,90,66,176,212,125,30,202,198,183,206,190,88,11,232,98,208,135,119,207,149,92,228,149,15,190,64,124,23,94,180,88,87,24,108,252,30,187, +164,156,52,93,191,30,9,180,55,129,181,139,95,114,159,6,71,212,101,128,92,72,64,164,206,159,233,127,187,54,190,37,255,203,30,108,60,54,2,186,24,241,69,68,198,207,218,155,45,24,207,12,121,13,190,32,226,54,8,95,224,247,94,11,18,129,116,29,63,214,8,254,103, +18,125,34,50,220,3,24,190,148,45,57,122,197,8,45,17,254,232,2,65,108,139,88,82,114,169,59,204,212,190,37,25,189,34,178,66,245,90,169,228,104,139,72,164,70,147,90,37,8,235,88,175,209,209,113,242,27,186,64,161,58,197,212,63,17,19,190,108,115,124,254,104, +155,191,73,68,206,0,204,41,83,34,2,148,72,40,85,235,156,139,210,137,198,250,222,169,235,19,145,5,230,47,213,253,119,38,0,109,58,1,205,44,97,130,176,30,177,125,64,98,167,47,98,114,166,9,149,47,146,212,37,34,105,172,176,195,81,213,173,9,128,14,224,41,73, +2,8,70,109,140,170,19,143,250,25,253,19,177,58,255,114,151,41,139,187,100,0,90,18,80,81,206,4,35,55,58,218,132,29,63,163,127,34,70,84,187,78,202,61,218,245,9,34,50,5,112,74,89,19,140,222,242,118,188,137,58,126,70,255,68,140,56,85,223,188,19,126,219,231, +73,34,50,209,141,127,73,185,19,70,113,15,224,95,161,233,222,94,166,252,161,235,78,184,239,249,1,153,92,99,252,47,1,252,35,128,43,60,12,130,249,192,45,69,24,118,254,147,189,124,249,129,198,160,66,51,121,237,119,174,1,17,0,115,52,99,66,219,249,225,11,0, +179,231,206,190,102,226,188,54,201,58,29,126,71,50,211,193,104,237,125,30,197,218,239,255,224,86,36,2,96,5,224,108,95,231,127,48,1,208,77,49,68,51,121,141,36,128,232,75,201,219,251,30,218,27,196,22,187,94,39,154,163,35,35,246,66,1,224,191,17,145,255, +99,71,253,106,73,65,137,135,49,225,67,218,69,162,71,187,88,30,122,59,110,39,249,66,85,254,41,153,48,113,0,238,55,162,249,217,75,209,252,142,250,249,119,0,254,25,137,151,2,136,131,49,64,211,228,252,9,77,90,181,238,64,247,214,201,64,65,98,64,116,128,57, +128,209,174,65,80,111,4,96,77,217,99,190,60,136,240,31,209,47,212,201,215,125,61,76,201,233,255,6,224,127,69,2,119,4,16,189,162,196,195,204,255,37,154,91,212,150,61,234,102,73,98,64,236,136,175,58,152,175,19,72,15,74,61,2,48,161,34,19,202,84,215,239, +247,94,116,193,90,119,212,199,59,53,176,19,52,35,173,23,92,22,226,9,20,26,188,84,120,24,251,59,19,145,247,158,245,181,192,67,41,161,37,6,204,172,18,43,52,199,252,58,189,238,92,122,82,226,1,154,230,192,19,174,91,54,184,93,143,236,251,140,234,119,208,195, +75,60,204,173,88,40,1,152,128,165,0,226,49,214,83,255,197,198,127,155,136,200,169,1,93,222,204,22,240,84,66,62,184,66,211,236,215,185,221,18,15,74,123,65,6,155,180,179,159,29,218,136,210,147,238,85,248,245,152,106,141,68,174,11,38,58,69,137,151,175,251, +61,61,164,211,186,71,29,111,203,6,67,146,130,36,49,87,199,223,155,189,18,79,138,90,1,24,3,120,203,53,141,82,9,107,203,206,254,25,195,120,247,196,127,90,130,165,0,226,49,10,252,154,250,127,10,239,35,210,253,246,167,100,240,21,37,238,1,140,125,144,78,241, +172,156,36,2,246,21,175,141,236,107,11,105,252,61,116,108,0,224,251,11,198,124,1,150,2,136,6,47,165,254,159,210,155,247,125,54,5,246,184,39,74,37,3,45,49,160,253,205,220,241,7,33,0,27,68,160,2,83,86,86,162,251,90,163,251,232,163,98,231,220,13,94,31,225, +58,67,83,10,152,82,5,178,198,8,77,234,127,184,229,255,95,139,200,199,4,246,72,177,70,8,152,37,8,143,91,52,189,38,19,223,15,22,3,138,120,166,27,145,172,212,143,162,173,59,252,164,34,224,141,166,191,215,48,85,18,48,163,90,100,137,161,58,255,209,142,127, +174,211,99,88,70,246,205,96,131,16,48,48,243,19,237,79,1,92,132,12,188,196,144,18,142,116,51,150,36,3,221,59,252,24,211,249,59,234,79,133,221,238,166,96,63,64,190,40,176,93,221,255,57,152,108,10,236,120,63,149,120,184,16,137,132,160,59,167,95,3,152,118, +125,156,47,122,2,176,161,124,67,221,156,37,152,158,218,5,243,53,135,159,77,122,251,133,166,191,215,176,80,18,112,69,18,144,149,243,63,81,251,82,28,240,247,68,209,20,216,113,134,160,164,77,222,219,38,79,44,234,139,68,162,124,195,53,229,227,180,172,7,172, +208,164,145,90,86,153,93,83,219,22,77,127,219,144,0,54,5,230,129,93,154,254,94,67,239,147,2,141,239,185,54,91,59,162,61,126,100,143,103,136,168,204,42,145,42,96,123,69,103,137,135,155,185,114,73,83,205,213,233,79,115,137,64,94,209,133,59,108,223,196, +245,28,102,74,2,166,36,1,73,59,255,145,58,255,97,71,127,167,247,73,129,134,237,113,91,194,205,37,59,112,139,135,27,72,107,0,203,24,237,177,36,162,128,3,0,55,29,110,108,107,184,94,115,250,116,80,15,235,190,75,211,31,73,0,157,255,167,30,108,132,137,73, +129,6,179,3,35,0,199,137,126,230,12,192,199,20,108,177,36,160,112,67,117,254,131,132,20,172,77,237,79,209,212,243,233,144,126,93,247,10,187,53,253,109,131,26,156,20,152,34,74,188,60,233,239,80,36,223,20,120,0,25,40,215,8,65,74,165,130,165,146,128,168, +179,176,18,185,130,245,225,4,130,59,253,156,26,248,246,92,247,82,73,95,31,155,122,170,153,0,30,15,76,3,67,141,252,71,61,7,9,31,83,63,105,211,193,190,29,37,70,6,150,0,254,138,153,252,73,196,202,116,142,102,134,64,236,184,86,167,207,8,98,187,117,239,59, +227,67,18,64,231,191,175,222,188,79,97,152,150,199,224,45,149,50,193,133,136,252,69,2,224,79,121,186,172,253,134,192,28,205,37,73,172,233,239,182,238,190,122,61,90,18,112,165,36,128,107,20,23,218,147,67,39,158,156,127,139,100,106,195,158,247,244,72,131, +185,152,27,8,163,236,5,145,8,149,229,18,187,79,239,178,128,54,197,127,193,238,253,189,215,255,155,199,181,95,170,65,191,2,27,3,99,115,254,35,117,254,67,248,239,13,154,138,200,159,92,134,189,246,247,16,15,147,97,99,44,17,76,208,148,4,162,177,21,18,145, +114,196,218,233,31,108,206,115,98,198,225,2,77,58,215,55,120,58,32,62,231,255,41,176,157,72,110,92,112,128,253,94,33,206,251,98,162,202,2,73,36,202,16,163,243,191,82,199,95,115,59,119,98,12,46,3,111,234,54,19,176,224,138,152,68,177,17,249,135,6,79,6, +116,179,247,75,37,2,39,36,1,25,18,128,200,156,127,155,230,31,179,25,168,179,245,223,119,204,111,215,88,128,99,131,45,59,255,46,198,251,118,141,247,44,247,117,102,7,10,52,87,201,199,82,30,136,130,4,196,64,0,186,152,244,230,195,241,95,160,169,239,51,77, +220,237,166,191,131,157,25,15,11,60,110,14,36,194,99,189,217,175,48,246,110,60,25,208,79,64,120,166,63,214,137,128,249,73,145,98,124,177,99,232,246,191,98,196,223,219,70,183,152,249,89,162,25,20,116,165,191,146,240,133,65,59,100,230,68,127,181,58,8,140, +39,3,250,205,8,88,47,13,152,62,29,32,134,23,216,186,243,167,227,239,119,253,111,208,223,228,182,174,12,59,251,2,194,160,128,173,122,255,107,224,201,128,188,137,128,89,18,96,245,58,224,51,0,231,70,23,115,14,224,140,205,125,89,147,191,22,11,37,0,215,224, +188,0,95,81,255,16,205,240,24,139,41,255,104,35,193,4,108,70,137,166,12,107,117,150,192,95,34,114,65,2,176,221,66,222,24,92,192,149,70,252,23,220,110,217,146,191,167,208,206,11,184,102,54,192,75,212,127,140,48,231,251,187,0,79,6,244,111,63,198,176,219, +31,96,110,92,180,24,91,188,2,182,154,190,90,92,107,212,79,227,222,239,250,87,136,247,110,135,95,178,1,34,2,231,28,23,246,16,3,213,200,176,192,195,72,223,34,242,79,250,147,119,125,120,241,35,23,176,55,102,216,92,83,168,53,2,96,173,227,127,5,96,196,116, +191,151,181,79,225,86,199,37,128,255,12,224,127,22,145,255,170,223,197,197,221,31,127,35,34,255,172,114,252,7,0,255,59,226,191,68,38,137,91,228,34,177,41,165,146,114,75,58,99,234,100,192,145,161,197,26,27,115,254,215,0,10,58,127,111,140,61,133,43,157, +239,1,252,79,173,243,87,12,184,194,59,163,64,211,3,242,239,214,50,1,255,73,237,195,60,242,111,27,0,184,209,83,46,68,159,209,109,99,187,11,181,229,86,48,84,95,199,12,192,70,244,119,103,68,38,43,0,21,211,116,222,214,62,214,17,207,155,184,18,145,234,137, +239,251,95,0,252,63,104,142,12,46,184,226,175,58,254,18,205,248,215,18,192,92,68,70,79,200,116,130,184,38,195,61,25,9,130,199,3,125,218,153,17,154,65,94,86,178,1,38,134,68,89,33,0,86,82,255,183,104,82,254,220,148,254,214,222,250,113,191,109,240,108,115, +151,115,174,6,240,86,9,192,45,137,192,86,142,191,104,247,163,136,148,207,200,181,66,188,253,34,45,106,17,249,200,229,247,26,108,76,97,227,126,1,19,165,0,49,176,40,99,0,159,13,44,200,23,17,25,115,155,120,93,251,216,175,117,190,87,194,56,123,225,27,215, +155,0,22,36,2,91,57,254,7,3,37,34,47,200,118,168,114,140,185,47,128,199,3,233,115,242,36,0,70,186,254,153,242,15,179,246,161,110,247,235,10,175,102,139,52,226,248,241,196,127,106,137,192,28,77,42,56,167,25,2,237,89,254,33,154,51,219,79,58,254,53,188, +217,66,198,86,162,186,125,193,219,3,253,219,31,11,37,129,224,167,2,66,19,128,9,194,214,242,230,234,252,217,145,235,119,221,43,196,157,190,221,202,96,111,49,211,162,157,33,112,171,191,46,244,39,53,50,48,80,39,95,168,227,255,128,237,207,242,111,117,118, +58,129,190,0,206,8,240,111,135,134,74,2,66,14,15,122,178,119,40,121,2,160,209,255,247,192,206,191,100,189,63,8,243,254,22,233,235,175,208,204,131,152,108,249,173,219,18,157,229,154,243,159,39,66,6,54,157,254,31,107,255,188,75,198,239,180,7,121,91,5,103, +4,248,183,71,3,52,217,184,144,36,224,93,168,44,192,111,1,63,58,228,70,13,202,186,50,103,220,177,26,232,149,18,198,93,178,69,197,14,206,178,77,139,151,17,147,129,174,156,254,62,50,132,136,76,156,115,51,196,219,23,112,233,156,91,48,35,233,49,2,110,2,192, +97,224,12,210,37,128,32,205,160,65,50,0,129,163,127,58,255,112,206,63,214,179,254,123,101,139,244,4,192,33,181,233,245,204,192,253,218,239,173,16,130,117,135,223,254,188,237,192,233,175,227,250,169,163,128,17,68,117,135,172,57,7,5,133,177,81,33,73,64, +144,44,128,100,38,104,58,255,48,235,61,80,194,23,163,243,223,91,103,122,56,222,186,73,8,150,107,255,110,243,247,219,68,63,237,123,110,235,232,7,79,252,190,107,135,191,137,103,143,2,26,55,232,135,96,129,166,57,140,229,73,250,166,180,8,64,64,103,64,231, +31,206,249,199,58,232,231,160,198,44,231,103,14,240,38,1,184,95,35,0,203,103,126,15,0,255,85,68,254,81,223,243,239,1,252,221,154,83,199,19,191,127,251,4,1,240,99,164,94,56,10,184,197,26,84,136,179,236,196,65,65,121,145,128,165,102,1,188,174,119,8,2,16, +226,182,183,157,211,136,68,214,206,255,224,59,32,12,52,185,190,70,0,254,71,17,249,39,125,215,191,5,240,31,94,32,0,161,113,80,122,212,232,76,120,146,0,219,182,171,134,255,163,165,222,175,12,14,113,23,128,111,102,53,71,220,195,102,98,198,101,132,206,127, +14,96,216,193,29,16,133,129,111,217,108,202,43,245,71,90,231,175,17,246,63,105,48,48,68,191,233,252,32,178,212,181,44,17,223,61,2,67,196,117,53,118,74,24,5,208,23,239,165,7,175,4,64,163,34,159,14,161,141,228,200,160,253,51,232,75,221,68,49,225,26,77, +179,223,162,131,191,171,52,252,157,147,45,255,157,37,71,120,16,180,169,174,132,173,139,97,182,65,165,123,137,240,8,245,25,35,245,33,222,244,92,125,100,178,25,0,223,14,161,178,116,247,114,102,206,191,138,236,181,191,138,72,151,100,209,106,195,227,234, +169,190,6,253,119,43,163,239,220,137,81,20,145,165,150,2,191,146,4,16,91,232,203,34,128,29,243,234,35,125,19,0,159,41,142,175,28,170,65,231,191,37,78,123,24,197,106,181,244,49,217,243,191,69,157,1,216,48,236,103,0,98,155,191,95,233,248,108,194,47,9,152, +2,184,74,212,71,250,107,2,124,97,46,122,47,81,14,128,130,169,127,239,206,191,66,92,29,215,251,12,247,217,86,22,63,140,102,1,158,109,168,51,210,184,248,20,150,34,242,166,135,53,138,241,50,33,142,12,246,111,215,6,104,78,218,248,210,147,55,190,124,151,207, +12,128,207,136,232,140,206,159,206,255,21,180,205,126,179,158,12,134,69,231,127,251,82,73,76,255,219,173,193,247,238,69,150,186,246,67,196,213,28,120,169,123,141,240,151,5,88,2,240,121,89,147,55,95,233,147,0,148,158,158,115,79,134,76,231,255,10,186,108, +246,11,77,118,119,193,164,163,255,39,132,142,245,98,63,84,7,74,163,196,135,36,192,14,9,152,160,153,177,145,146,175,76,50,3,48,166,186,210,249,191,128,171,142,155,253,98,33,0,171,109,136,177,225,102,192,162,207,8,79,167,13,94,69,164,199,36,1,254,225,203, +183,36,153,1,240,49,151,123,197,232,159,206,255,5,156,122,154,6,89,24,252,246,73,79,255,111,244,4,96,141,8,84,136,171,57,144,36,192,127,22,192,7,57,246,118,135,133,23,2,160,53,81,31,70,145,93,255,116,254,79,18,67,52,87,173,250,114,108,22,51,0,177,19, +128,210,163,145,255,19,118,143,68,146,4,132,133,15,31,83,168,207,76,38,3,48,76,104,113,232,252,157,27,69,230,252,75,207,71,66,173,221,66,55,223,165,217,81,255,95,107,141,113,111,61,70,122,83,37,28,177,144,128,115,61,209,64,164,227,99,188,172,231,81,74, +43,195,115,255,94,156,255,48,34,231,63,71,115,28,212,247,213,170,214,78,0,92,120,250,51,189,70,69,158,109,73,76,39,4,6,0,110,72,2,232,99,114,38,0,115,170,167,23,231,127,131,56,174,245,189,213,200,127,233,89,70,101,34,81,203,212,160,254,121,149,109,100, +39,4,72,2,232,107,204,18,0,31,27,151,231,254,251,53,190,163,136,156,255,149,136,148,129,102,65,12,13,202,98,103,57,232,159,177,214,21,239,93,182,145,157,16,32,9,240,3,31,118,197,11,217,77,41,3,80,83,47,123,115,254,21,128,111,145,56,255,47,158,58,253, +159,67,97,76,30,147,64,127,54,41,217,170,78,197,112,135,192,0,192,29,27,3,123,197,44,149,15,57,226,90,18,91,56,255,88,106,254,167,34,50,206,45,74,125,1,247,135,92,107,172,127,246,222,208,247,4,149,109,100,119,8,240,116,64,220,25,0,18,128,61,152,47,145, +167,243,247,125,204,239,37,88,58,1,48,49,242,119,36,35,219,200,142,9,146,4,208,215,100,67,0,88,247,202,215,249,151,22,186,115,245,50,29,75,198,33,53,2,48,240,117,62,250,21,18,16,211,49,65,146,0,250,154,44,8,0,145,159,243,191,71,79,183,249,237,137,194, +144,108,110,187,184,235,192,224,5,65,38,140,175,234,28,73,0,65,2,176,5,124,212,76,222,114,57,59,113,254,231,145,56,255,222,110,243,59,0,101,98,209,191,197,44,128,25,25,171,238,21,136,227,88,216,165,115,238,51,45,92,52,190,102,225,227,67,124,17,0,31,70, +186,208,20,44,177,191,243,191,132,223,107,47,15,113,254,165,193,43,159,173,164,6,87,232,246,28,255,212,80,164,107,106,143,171,14,150,145,144,128,177,238,113,98,127,27,89,120,210,193,164,8,128,47,67,93,82,69,15,114,254,85,4,175,122,101,212,249,251,138, +12,182,114,216,93,202,71,255,46,43,131,129,172,141,89,94,39,1,215,17,236,159,138,36,32,10,31,227,197,190,29,121,218,32,179,196,22,39,37,199,63,112,206,221,196,226,252,69,164,50,234,252,45,101,0,38,125,144,10,202,248,101,18,32,34,35,196,49,48,168,114, +206,221,88,104,168,58,80,247,96,0,0,22,132,73,68,65,84,36,1,8,235,51,125,54,1,250,56,79,252,129,250,185,155,243,71,51,221,47,6,226,116,21,120,192,207,107,178,180,34,195,131,206,254,191,96,144,166,48,50,19,192,232,184,229,86,78,85,36,36,160,68,51,53,144, +36,192,158,143,241,182,207,124,18,0,95,125,0,204,2,108,103,68,135,0,190,35,142,35,45,95,45,59,127,99,145,233,52,210,191,123,167,125,110,89,17,34,34,1,67,0,223,57,58,120,39,226,233,67,247,188,53,54,167,70,0,128,56,82,217,161,21,57,166,185,254,167,58,129, +205,58,172,56,165,62,111,241,155,144,108,237,68,2,98,152,26,216,222,31,48,162,101,52,227,91,146,36,0,181,167,231,156,48,173,245,162,243,175,16,207,92,255,83,35,211,253,98,113,74,243,46,206,254,191,224,212,102,176,209,237,30,69,196,170,186,27,11,9,248, +198,89,1,47,218,205,1,128,147,196,124,101,146,25,0,102,1,158,87,226,75,196,53,215,127,18,145,120,45,244,159,76,18,121,70,12,178,78,141,4,0,205,172,0,158,16,8,236,83,250,232,225,121,246,89,158,29,80,237,105,243,46,68,228,29,117,246,17,123,189,65,60,35, +44,163,114,254,90,67,189,51,240,42,111,250,62,33,161,231,160,191,27,248,214,247,198,134,64,189,38,183,42,34,242,61,3,240,209,240,105,155,16,246,243,14,126,202,124,183,122,253,116,114,25,0,192,95,106,163,112,206,141,169,186,209,53,251,197,24,249,195,136, +108,175,125,24,108,45,49,92,83,230,73,103,2,216,28,248,24,103,240,215,227,83,251,252,48,223,4,192,103,23,241,167,220,123,1,52,234,184,67,28,245,126,75,55,250,197,232,140,166,137,62,43,9,2,16,33,9,24,0,184,203,189,47,64,125,200,167,84,247,214,145,231, +13,48,131,191,51,142,3,196,49,214,182,23,165,117,206,125,67,60,41,71,51,55,250,145,0,144,0,120,32,1,31,17,199,37,66,64,211,23,240,45,227,96,234,204,99,0,117,239,187,172,21,226,54,64,102,1,250,117,254,165,70,253,177,28,235,105,157,255,44,98,177,135,110, +74,187,242,89,175,213,103,93,103,46,243,67,228,87,35,158,155,4,161,182,228,46,183,146,64,234,209,127,40,2,48,241,248,172,65,68,81,112,23,10,251,25,77,179,95,65,231,239,77,230,185,69,255,33,246,177,101,217,239,75,2,98,186,78,24,106,83,238,50,187,81,240, +18,126,203,167,23,190,63,240,40,144,226,251,60,75,60,74,125,58,160,115,174,208,121,254,227,136,94,59,133,200,31,8,159,138,94,133,40,157,232,51,87,153,203,190,11,91,24,219,0,158,177,222,35,80,32,97,168,207,240,185,54,183,125,206,240,176,148,1,8,193,116, +46,83,45,5,40,35,191,67,124,23,33,157,37,224,252,45,56,161,105,166,207,142,158,0,40,9,168,17,79,99,96,139,50,229,108,128,250,10,223,153,227,73,136,111,61,10,164,244,19,207,209,67,17,89,116,188,21,67,117,206,221,233,119,197,70,110,78,35,237,246,127,10, +161,107,209,57,19,128,36,46,255,138,236,116,64,139,129,102,3,238,18,204,176,142,225,183,140,186,74,200,30,110,237,192,198,206,63,70,9,200,109,224,156,59,119,241,162,74,76,143,67,98,105,224,251,151,33,5,144,152,46,85,17,239,235,243,20,178,172,206,185, +81,0,217,5,11,78,143,2,202,58,4,227,185,140,185,118,165,41,183,239,136,247,120,99,74,145,191,133,107,105,45,28,199,155,102,190,6,185,103,2,90,156,161,25,30,244,57,226,253,92,32,76,211,248,69,168,111,62,10,168,236,11,248,191,50,179,189,244,98,16,153,98, +158,56,231,190,35,206,116,127,146,206,95,65,2,192,62,0,146,128,199,246,117,236,156,251,238,156,59,137,233,197,213,39,132,184,36,237,42,219,145,203,218,189,30,2,151,145,200,231,68,55,83,236,24,39,170,191,211,156,211,255,107,114,8,89,6,152,38,170,91,23, +9,236,251,155,88,50,52,58,236,40,4,138,144,223,29,178,4,16,42,11,0,0,149,101,18,176,22,241,79,16,207,153,254,151,24,110,146,4,0,192,31,153,71,255,22,222,229,143,20,21,75,68,206,2,217,198,174,51,100,55,218,40,104,54,35,160,190,32,68,127,216,85,136,163, +127,22,179,0,75,102,2,146,138,248,91,76,152,189,74,191,161,53,80,227,148,153,40,170,103,217,78,18,178,7,230,74,3,206,185,203,80,25,60,11,122,123,20,250,5,148,1,133,106,130,168,148,157,14,2,42,224,192,57,247,57,161,136,191,197,181,136,84,9,115,215,50, +224,179,87,150,238,77,48,48,20,40,217,17,181,186,135,110,19,249,156,2,192,68,137,192,103,3,118,247,14,64,40,27,117,97,33,250,63,50,162,24,23,1,13,200,16,205,80,139,210,179,2,150,154,129,248,1,255,231,78,251,198,60,224,198,202,193,233,88,172,123,135,124, +167,50,113,93,27,193,239,244,84,31,68,96,12,224,135,70,224,222,109,47,194,94,145,190,10,24,244,218,35,0,218,5,121,22,88,33,111,84,25,139,30,21,111,184,22,237,223,36,234,36,219,17,191,169,119,182,134,28,66,67,2,96,103,45,124,217,199,18,241,220,27,176, +11,42,181,189,109,86,160,55,167,172,101,187,111,106,123,67,158,166,58,179,98,31,197,146,38,56,231,106,3,155,121,169,198,236,107,23,163,106,157,115,31,148,193,143,18,139,242,95,114,254,179,148,63,82,83,151,63,66,201,88,68,6,70,229,178,4,240,123,160,199, +191,73,157,116,170,115,172,3,202,216,23,22,106,131,167,34,114,219,145,220,62,169,13,14,189,119,110,69,164,180,34,104,107,4,160,0,48,51,164,224,51,85,196,153,46,220,114,11,103,63,80,182,62,68,250,169,201,77,252,105,169,54,221,163,158,142,208,156,25,14, +129,43,171,189,21,122,36,239,56,208,227,63,234,92,125,234,94,122,168,213,6,215,0,150,175,145,2,37,232,31,212,6,143,96,167,71,100,5,96,104,169,243,255,55,75,171,44,34,11,61,51,126,110,228,149,134,235,202,163,147,71,23,250,179,142,220,28,253,83,56,205, +193,249,175,233,69,72,99,104,21,33,9,64,105,92,54,93,217,200,169,115,238,20,25,93,115,174,107,91,66,203,196,107,19,160,55,215,187,128,237,44,235,216,218,177,63,177,40,37,231,220,12,137,158,239,77,20,87,137,119,252,111,234,103,141,112,165,42,179,169,238, +192,165,17,83,169,85,15,178,158,0,56,1,17,11,230,34,98,238,180,138,85,2,48,68,115,197,45,65,197,182,168,159,161,46,161,185,22,145,145,113,217,4,203,2,136,136,100,166,135,12,148,226,193,123,139,189,81,71,22,37,165,130,250,66,157,49,143,21,50,43,127,4, +30,109,26,67,137,101,154,233,218,132,64,137,52,79,6,164,134,47,86,27,163,143,172,74,76,199,199,222,82,119,108,27,160,12,47,178,8,233,100,234,8,228,83,103,186,54,33,108,228,18,236,63,178,142,91,203,163,208,143,140,11,111,4,224,158,58,100,18,167,169,31, +247,123,6,161,154,220,230,49,204,13,215,119,12,53,180,38,59,103,168,123,240,20,132,69,204,17,230,142,129,52,8,128,50,220,17,152,230,178,134,171,4,175,246,125,21,218,228,22,170,223,33,166,19,22,161,222,245,67,142,155,81,247,226,53,205,146,41,172,0,84, +214,51,164,71,17,40,247,12,233,143,149,141,9,247,8,59,181,49,36,66,70,152,36,0,219,145,180,81,166,186,89,129,217,82,83,235,17,67,134,244,40,6,73,234,249,114,54,5,218,192,40,195,186,127,104,2,112,31,83,185,69,223,245,62,179,53,10,45,243,37,3,37,51,248, +18,203,76,148,163,136,20,124,140,248,239,199,78,65,177,103,25,127,127,168,20,115,29,161,172,234,204,214,200,130,141,172,25,40,5,199,149,229,166,191,95,116,38,54,233,114,0,70,48,100,53,104,229,9,189,11,57,228,38,186,17,203,129,71,214,190,201,56,75,197, +249,0,97,157,127,21,211,11,31,197,38,97,21,48,51,1,126,177,2,211,139,33,107,203,204,0,196,179,86,185,235,42,157,63,9,0,73,64,98,184,136,225,8,90,207,40,3,61,247,54,198,104,86,223,249,54,179,181,178,34,251,5,88,10,160,243,79,149,0,144,4,120,197,60,166, +154,86,143,8,117,254,63,230,11,150,234,204,214,202,146,125,28,35,220,60,6,58,127,18,0,111,36,128,76,183,95,156,229,46,0,189,155,34,212,61,226,117,196,162,11,69,94,6,186,102,220,187,68,159,248,43,246,75,208,142,98,95,1,101,186,239,193,51,176,125,224,107, +14,119,172,111,129,80,53,213,85,204,167,46,244,221,87,153,173,153,37,249,215,0,190,114,251,118,142,123,52,151,251,92,196,254,33,71,137,40,250,12,205,132,54,78,195,234,208,249,0,24,83,12,0,152,254,143,241,27,142,169,182,128,238,97,78,82,237,14,215,0,134, +169,28,135,62,74,101,85,68,100,169,87,165,254,69,29,237,4,23,57,31,165,106,17,120,252,111,157,128,8,67,125,195,80,215,46,247,44,192,18,192,5,136,46,240,151,136,36,53,8,237,40,65,133,191,64,83,18,224,77,130,251,227,158,141,127,63,193,227,127,241,126,3, +143,195,225,103,153,148,37,210,253,113,139,68,82,254,201,19,0,85,248,153,14,173,249,152,128,226,95,195,127,105,131,206,63,188,19,185,79,225,232,165,126,195,125,102,107,103,17,190,247,116,8,187,213,53,230,0,62,138,72,153,234,4,212,163,148,53,94,68,106, +17,41,208,92,151,121,31,153,226,253,5,224,157,150,53,188,178,221,28,111,250,123,10,154,66,14,85,75,174,19,18,101,168,111,57,102,25,224,167,45,156,248,182,129,106,187,222,169,45,139,233,72,226,61,154,235,206,135,108,130,78,200,152,59,231,42,231,220,204, +217,196,194,57,119,177,121,124,201,57,87,120,126,143,146,218,242,83,246,163,128,250,80,37,36,199,42,160,28,153,5,8,183,14,197,198,243,135,106,227,22,70,109,240,44,165,125,71,60,191,17,10,35,138,56,117,206,157,189,116,102,89,255,187,47,144,237,62,150, +253,36,160,110,20,137,237,183,80,96,54,235,241,90,248,180,121,103,47,188,199,80,109,91,109,36,240,42,114,212,7,225,134,112,37,154,90,225,16,253,223,36,118,11,96,6,96,186,109,106,201,57,247,29,128,47,229,252,200,148,215,35,217,255,64,152,1,64,247,90,186, +74,202,241,0,120,27,224,209,75,17,121,67,109,126,200,2,0,184,244,244,184,153,136,188,79,193,14,147,0,228,69,8,134,107,63,251,220,170,53,7,176,80,37,155,1,88,236,211,68,162,153,129,59,79,159,62,23,17,78,79,123,144,125,200,219,236,190,138,200,89,98,242, +156,32,220,45,158,209,221,166,152,16,25,123,127,128,237,43,214,236,112,113,128,45,110,237,240,140,1,206,99,252,70,17,108,48,162,70,65,234,103,148,178,120,38,26,95,244,212,177,93,121,252,116,158,21,126,140,144,181,227,20,59,142,235,128,4,96,132,52,134, +42,117,133,177,199,44,64,133,61,70,18,43,105,152,61,183,110,1,108,49,51,0,132,119,166,238,43,5,157,92,202,249,64,185,15,0,124,71,184,249,255,239,82,51,98,158,179,89,155,96,25,32,92,22,128,178,55,140,35,138,192,180,193,244,229,128,38,148,248,47,17,99, +40,231,191,74,49,130,9,124,47,192,128,221,221,193,246,60,47,102,34,1,32,246,116,66,94,28,14,152,254,15,37,251,167,80,39,44,215,89,166,107,106,17,23,30,9,89,73,113,147,0,16,54,55,205,148,51,255,31,16,120,248,79,104,39,153,50,185,225,80,160,53,232,158, +247,213,23,65,242,69,2,64,236,232,132,62,120,122,220,132,18,55,101,172,82,206,0,212,153,175,173,53,248,218,251,31,40,106,163,68,144,34,48,73,0,124,29,65,99,243,223,175,178,191,67,184,219,255,32,34,146,184,124,93,192,199,111,125,46,61,35,125,95,192,79, +51,32,143,98,50,3,64,108,137,146,209,127,16,99,56,12,233,252,17,215,188,244,24,191,113,200,134,180,96,54,160,164,168,73,0,136,237,192,244,127,24,132,30,190,51,203,64,198,139,204,215,216,26,124,69,229,44,3,144,0,16,219,70,42,30,158,113,207,129,25,143, +162,255,208,205,127,22,156,99,14,36,231,152,218,254,0,61,158,233,227,150,64,102,94,72,0,136,45,28,145,175,141,194,122,220,99,132,60,251,223,162,206,64,206,161,191,145,51,1,2,217,2,150,95,72,0,136,215,81,144,0,4,193,137,129,119,200,161,4,48,227,90,231, +73,0,60,218,54,130,4,32,90,120,97,201,188,20,227,81,100,82,34,124,147,210,125,14,243,24,244,27,239,3,191,70,169,107,78,248,181,5,204,0,144,0,16,6,54,201,45,197,252,8,22,26,195,22,25,201,219,194,183,86,84,123,239,54,129,4,128,4,128,120,5,127,120,120,6, +163,255,135,232,191,128,141,198,176,156,214,196,194,183,158,232,218,19,254,214,228,45,197,76,2,64,188,12,31,70,105,70,49,255,196,216,200,123,228,52,142,121,201,181,55,7,31,54,129,25,0,18,0,194,0,22,20,129,153,163,127,57,146,50,43,223,202,251,1,242,36, +160,4,9,128,89,135,212,59,244,236,47,209,212,254,173,56,128,156,214,196,10,1,29,128,131,129,90,155,80,83,10,25,174,59,69,96,138,0,148,0,110,122,126,204,74,68,6,148,181,43,0,124,55,100,128,37,51,249,59,35,175,178,4,240,158,67,177,188,173,201,71,146,13, +102,0,8,70,154,161,49,54,244,46,57,158,202,176,242,205,3,176,23,32,103,61,36,1,32,136,12,163,127,14,131,33,90,240,68,0,65,2,64,16,140,254,131,32,199,172,204,140,58,65,16,36,0,4,225,51,250,47,13,70,255,57,118,96,91,251,230,19,78,7,36,72,0,8,34,109,156, +211,25,242,155,35,210,13,159,248,157,230,129,4,128,72,27,217,222,203,237,156,27,195,230,48,18,150,0,108,96,168,58,146,43,56,168,135,4,128,200,192,17,14,50,252,230,2,192,39,174,62,241,10,62,229,216,16,200,129,72,36,0,68,96,240,86,174,94,113,9,59,67,127, +54,193,41,108,118,48,64,158,165,0,222,66,74,2,64,100,130,50,179,232,102,100,249,155,51,157,204,104,249,155,71,170,51,180,9,4,9,0,225,21,115,15,207,56,206,69,152,154,218,60,167,90,153,35,61,214,179,30,231,153,165,197,125,216,132,57,53,159,4,128,120,25, +11,15,207,24,102,84,231,188,132,159,27,22,137,180,80,168,238,228,64,146,11,248,41,1,44,168,86,36,0,196,203,240,149,26,173,50,48,108,21,128,17,85,138,216,19,35,213,161,212,49,78,204,182,17,36,0,36,0,175,224,83,202,41,78,141,106,152,250,39,14,197,121,202, +217,50,207,87,98,147,0,144,0,16,175,160,246,244,156,212,47,65,249,6,187,93,255,68,60,24,168,46,165,28,253,251,218,39,53,213,137,4,128,120,1,218,28,117,239,49,11,80,38,24,213,140,193,161,38,68,119,72,114,64,144,238,125,95,179,49,238,35,104,252,36,1,32, +178,202,2,0,192,101,74,165,0,61,190,245,153,42,68,116,140,207,41,29,13,212,61,239,179,201,113,74,21,34,1,32,236,109,150,2,192,77,34,70,109,136,76,58,183,137,32,184,84,29,75,1,55,240,123,58,166,166,250,216,131,80,4,102,157,217,18,126,47,231,152,136,200, +105,228,17,205,119,68,88,247,23,17,201,84,199,93,132,175,189,0,240,62,230,116,182,115,238,18,126,79,1,173,68,132,253,56,204,0,16,70,179,0,0,80,169,97,136,213,249,223,128,77,127,177,173,89,140,40,0,220,196,250,254,1,156,127,8,91,70,144,0,144,0,236,75, +2,34,52,110,231,136,184,233,47,161,180,242,46,24,70,254,238,231,145,233,216,192,57,247,13,97,230,127,144,0,144,0,16,187,64,68,166,240,119,26,224,17,9,136,41,194,9,20,209,116,13,102,46,226,67,52,25,51,157,99,112,131,48,67,177,238,213,150,17,36,0,196,142, +24,7,140,112,190,91,63,34,152,136,243,39,72,2,250,220,35,37,128,59,132,203,184,140,169,38,36,0,196,126,89,128,9,128,85,192,168,244,198,57,103,242,82,148,196,156,63,75,0,36,1,93,239,143,129,115,238,28,97,123,99,86,106,195,8,18,0,98,79,92,4,126,254,25, +128,59,43,217,128,192,181,204,62,201,86,110,72,233,155,43,231,220,55,43,68,121,45,234,63,203,220,118,17,36,0,73,16,128,85,224,119,40,52,27,16,180,65,80,155,229,238,192,11,126,8,123,24,41,81,30,6,220,31,3,205,70,248,62,227,255,100,244,79,2,64,2,64,28, +8,61,111,124,102,228,117,42,52,189,1,159,125,19,1,189,149,237,14,105,94,237,203,18,64,26,104,137,114,21,192,241,127,70,51,7,163,50,34,139,51,142,254,37,1,32,186,33,1,19,0,183,70,94,167,189,68,200,11,17,88,75,249,167,60,225,143,37,128,180,190,235,210, +71,182,108,195,241,143,13,201,244,150,181,255,72,124,11,69,16,7,214,210,223,214,176,64,147,234,187,234,146,241,171,241,252,132,38,251,145,188,131,204,109,26,96,164,83,0,119,197,82,247,198,215,30,246,198,137,238,141,194,224,119,191,23,17,94,253,75,2,64, +116,108,52,47,224,239,246,174,125,48,81,34,80,31,104,220,142,213,112,230,20,25,191,201,37,101,170,107,252,35,163,181,109,203,120,215,135,172,177,54,247,157,192,118,3,236,87,17,57,3,65,2,64,244,98,56,107,0,127,24,127,213,133,190,103,141,38,29,184,216, +210,233,143,144,111,131,223,199,67,136,83,100,122,92,34,145,11,168,246,192,84,127,94,37,3,58,192,231,3,128,82,127,10,227,223,54,23,17,94,195,77,2,64,244,104,60,11,0,51,248,189,40,168,11,66,208,146,128,153,70,68,67,141,240,11,227,134,237,86,141,112,223, +56,205,165,110,234,156,59,131,159,81,186,190,214,238,208,125,177,212,125,49,192,67,115,164,245,125,177,137,21,128,225,107,100,159,32,1,32,14,55,160,35,0,223,40,137,254,35,26,141,188,166,30,28,201,149,136,84,153,232,175,143,82,214,45,154,108,82,13,251, +25,179,20,240,39,71,254,198,7,158,2,136,145,181,53,27,237,43,37,209,123,68,83,105,154,214,71,84,147,147,147,242,17,149,47,116,237,42,132,159,163,145,58,190,210,249,147,0,16,126,73,192,25,128,43,74,162,55,148,107,157,204,62,8,192,48,226,43,114,119,137, +254,215,211,220,189,18,0,221,39,51,112,112,84,159,184,98,211,31,9,0,17,134,4,84,36,1,189,224,116,227,24,147,175,35,77,57,52,80,149,158,158,83,175,237,147,26,192,41,213,186,23,231,95,81,12,36,0,68,56,156,161,169,85,19,221,224,235,19,205,120,11,79,207, +206,33,82,245,69,114,150,27,100,121,2,150,205,186,196,156,206,63,129,32,146,34,136,31,17,29,15,140,54,162,241,52,184,102,33,34,239,18,215,85,31,87,211,174,68,100,240,204,243,39,104,206,210,19,7,56,127,52,37,50,142,250,101,6,128,8,206,226,68,150,122,254, +150,229,128,30,156,191,194,199,40,230,34,228,101,50,30,156,127,225,41,3,48,123,97,175,84,220,39,7,239,147,33,157,63,9,0,97,143,8,208,184,245,227,252,129,181,154,114,207,40,19,150,115,229,233,57,53,247,73,47,248,202,180,63,9,0,97,159,4,176,225,169,91, +231,239,147,0,164,156,158,246,245,109,245,150,251,132,36,96,123,156,178,219,63,65,127,65,17,164,9,29,183,58,69,92,19,3,173,58,127,223,243,235,147,27,11,236,121,252,239,214,247,42,176,39,224,85,172,0,140,114,25,83,205,12,0,145,74,38,160,70,51,74,244,150, +210,56,204,249,171,60,151,240,119,218,34,197,72,235,179,167,231,204,119,169,79,51,19,240,34,110,1,20,116,254,36,0,68,156,36,96,41,34,37,128,47,148,198,35,156,238,89,203,244,101,8,143,181,97,46,149,232,191,64,128,243,255,59,146,0,150,205,30,227,139,136, +176,211,159,4,128,72,128,8,140,1,124,4,112,159,185,40,86,104,210,235,147,61,255,252,196,227,187,142,19,146,187,207,111,153,236,185,71,38,186,71,114,31,27,124,175,123,100,12,34,125,223,64,17,228,5,231,220,24,254,210,177,150,48,71,51,219,127,118,160,252, +22,0,222,122,122,231,232,123,1,60,215,254,239,69,164,56,240,125,135,74,34,114,156,169,241,133,142,159,25,0,34,253,108,192,59,228,213,27,112,141,199,179,253,15,129,79,135,124,30,179,208,181,113,242,210,227,35,235,14,246,199,12,77,185,34,167,253,113,11, +224,29,157,63,9,0,145,7,9,88,104,111,192,41,210,78,121,174,208,92,83,58,234,176,150,233,243,214,179,161,102,108,98,197,25,252,222,105,63,237,104,127,180,189,51,127,102,176,63,78,181,214,191,160,101,204,208,23,80,4,121,67,163,180,51,253,73,233,200,224, +53,30,174,243,237,90,102,11,248,43,3,0,17,222,181,238,156,171,60,71,255,7,167,255,95,216,31,19,0,199,137,57,254,11,0,23,108,242,35,8,2,206,185,194,57,55,113,241,99,233,156,27,245,44,171,11,207,223,244,35,166,17,193,206,185,97,128,117,191,232,249,155, +70,170,91,177,99,146,210,9,19,130,32,72,4,90,199,63,214,136,205,135,140,28,73,192,179,206,255,71,0,249,20,30,190,109,160,58,182,164,227,39,8,34,101,34,16,139,177,243,230,248,55,228,83,147,4,252,34,147,42,144,243,175,185,55,236,236,13,130,32,210,34,3, +85,32,135,103,214,184,169,76,66,225,179,49,253,24,56,231,206,3,202,163,34,73,126,76,136,66,201,132,32,136,116,137,192,80,235,223,139,128,198,109,170,206,119,96,64,30,33,229,240,221,57,119,98,64,6,165,190,75,40,44,140,16,160,74,117,51,152,28,116,111,14, +105,169,8,130,240,65,6,198,158,50,3,51,231,220,153,181,84,102,224,44,192,35,34,16,160,4,114,18,216,241,7,141,254,95,33,3,103,170,179,62,34,253,49,157,62,177,47,120,12,144,232,44,18,68,51,64,101,168,63,251,30,147,187,7,48,211,159,26,192,204,242,81,165, +0,71,2,95,194,84,127,110,187,62,215,173,4,227,3,128,145,254,88,32,99,189,28,253,235,88,102,195,62,246,5,47,232,33,72,0,8,243,89,2,117,20,5,158,30,8,179,84,131,214,98,22,219,185,228,0,231,221,183,197,114,205,97,44,215,126,5,128,213,83,83,17,157,115,31, +214,254,177,93,187,214,113,89,116,180,167,7,220,235,16,154,20,108,202,121,19,11,253,89,118,52,193,146,32,72,0,8,162,7,163,62,67,158,179,227,67,98,46,34,76,125,19,196,1,224,40,96,130,56,28,103,20,1,101,78,16,36,0,4,145,25,180,30,123,69,73,120,195,21,107, +224,4,209,129,237,162,8,8,226,112,104,109,119,129,180,238,83,176,136,21,128,130,51,236,9,130,25,0,130,176,146,5,88,2,168,40,137,222,81,209,249,19,4,9,0,65,88,35,1,83,0,95,41,137,222,240,53,182,91,17,9,194,180,205,162,8,8,162,91,240,84,64,47,96,215,63, +65,48,3,64,16,230,49,66,83,171,38,186,193,74,101,74,16,4,9,0,65,216,133,78,225,43,73,2,58,115,254,101,215,147,13,9,130,32,1,32,136,190,72,192,12,60,171,222,5,42,78,194,35,8,18,0,130,136,141,4,76,0,156,82,18,123,227,148,77,127,4,209,163,141,162,8,8,162, +95,24,190,47,192,186,243,159,80,12,4,65,2,64,16,177,147,128,17,128,9,56,40,232,53,172,208,164,253,25,249,19,4,9,0,65,36,67,2,134,104,174,56,38,9,120,222,249,151,172,249,19,132,31,176,7,128,32,124,177,237,198,177,149,0,230,148,198,47,152,211,249,19,4, +9,0,65,36,77,2,116,160,205,23,74,227,39,190,136,200,144,206,159,32,60,219,35,138,128,32,194,192,57,87,162,233,11,120,155,169,8,238,209,212,251,107,106,3,65,48,3,64,16,57,101,3,106,0,185,102,3,190,0,24,210,249,19,4,65,16,185,103,3,10,231,220,196,165,143, +137,115,174,224,138,19,4,65,16,196,99,34,80,58,231,234,4,29,127,173,37,15,130,32,140,128,61,0,4,97,52,35,128,102,148,112,133,120,143,13,174,208,244,56,92,112,150,63,65,144,0,16,4,177,27,17,24,160,185,9,175,2,240,33,146,215,190,85,199,63,21,145,37,87, +145,32,72,0,8,130,232,134,12,148,250,171,149,204,192,10,192,20,205,144,35,58,125,130,32,1,32,8,162,103,66,48,68,115,138,160,253,241,149,33,184,5,48,107,127,120,126,159,32,72,0,8,130,176,65,10,6,74,8,6,0,10,253,105,81,224,249,185,3,247,0,22,107,255,188, +208,159,165,58,251,37,157,61,65,164,131,255,31,36,166,129,112,251,243,66,102,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* flower_petals_png = (const char*) temp_binary_data_6; + +//================== garbage.png ================== +static const unsigned char temp_binary_data_7[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,0,0,0,2,0,8,3,0,0,0,195,166,36,200,0,0,0,3,115,66,73,84,8,8,8,219,225,79,224,0,0,0,9,112,72,89,115,0,0,14,146,0,0,14,146,1,163,29,31,35,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119, +119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,2,169,80,76,84,69,255,255,255,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,224,128,165,125,0,0,0,226,116,82,78,83,0,1,2, +3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,39,40,41,42,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,61,62,63,64,65,66,67,68,69,70,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94, +96,97,98,99,101,102,103,104,105,106,107,109,110,111,112,113,115,116,118,119,120,121,122,124,125,126,127,130,131,132,133,134,135,136,138,139,140,141,143,144,145,147,148,149,150,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171, +172,173,174,175,176,177,179,181,183,184,185,186,187,188,189,190,192,193,194,195,196,197,198,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,216,217,218,219,220,221,224,225,226,227,228,229,231,232,233,234,235,237,238,239,240,241,242,243,244, +245,246,247,248,249,250,251,252,253,254,54,30,65,241,0,0,15,212,73,68,65,84,120,218,237,221,249,95,21,245,30,199,241,97,115,197,194,93,83,202,5,73,173,72,201,22,91,205,37,45,77,73,179,220,10,69,178,92,208,18,41,210,138,212,220,202,91,153,230,198,53,176, +110,42,121,43,183,80,91,188,34,98,42,2,2,137,166,28,228,204,95,114,127,240,241,40,67,230,59,43,240,253,206,188,222,191,247,237,125,62,159,167,120,60,51,115,208,52,245,211,233,145,153,43,190,218,127,244,212,133,43,122,179,228,202,133,226,163,251,191,90, +49,243,145,78,26,105,225,68,14,93,144,95,174,183,88,202,243,23,12,141,100,11,45,149,206,105,187,170,244,22,79,213,174,180,206,236,162,249,19,51,62,183,86,151,36,181,185,227,99,216,72,179,38,62,167,66,151,42,21,57,241,108,165,217,210,127,67,72,151,46, +161,13,253,217,76,179,228,238,77,215,117,41,115,125,211,221,108,167,201,19,251,94,157,46,109,234,222,139,101,67,77,155,148,115,186,212,57,151,194,142,154,48,125,191,213,165,207,183,125,217,83,83,101,98,181,174,64,170,39,178,169,38,73,171,85,186,34,89, +213,138,109,121,159,126,71,116,101,114,164,31,251,242,58,15,84,232,10,165,226,1,54,230,109,70,94,214,149,202,229,145,236,204,203,76,13,233,138,37,52,149,173,121,151,185,97,93,185,132,231,178,55,175,50,69,193,253,235,122,120,10,155,243,38,79,135,116,37, +19,122,154,221,121,145,228,26,93,209,212,36,179,61,247,233,83,174,43,155,242,62,236,207,109,98,14,234,10,231,32,119,10,185,77,142,174,116,114,216,160,187,60,167,43,158,231,216,161,155,220,85,169,58,128,202,187,216,162,139,228,235,202,39,159,45,58,207, +120,221,7,25,207,30,157,166,93,137,31,0,148,180,99,147,14,243,142,157,11,176,199,242,215,101,206,153,221,12,153,147,185,46,255,152,157,139,211,239,176,73,103,233,103,245,209,159,171,121,179,186,53,119,185,110,179,242,174,90,172,87,203,237,33,206,178, +222,218,53,151,109,207,183,111,153,126,237,159,223,102,237,42,213,122,118,233,36,241,150,174,1,125,157,212,146,29,147,190,182,116,85,136,199,198,156,196,202,61,160,135,159,108,233,150,79,30,182,114,151,40,219,180,159,30,230,127,197,214,165,71,180,124, +207,136,116,243,71,149,174,246,96,159,182,147,109,58,214,139,79,201,209,244,169,139,166,85,179,217,167,221,68,154,62,3,118,34,65,150,174,9,39,76,159,24,227,123,68,236,102,132,217,76,247,221,38,79,217,219,246,153,181,29,193,70,109,230,115,147,137,158, +140,147,169,109,220,73,147,186,159,179,81,123,137,53,121,14,160,58,81,174,190,137,38,143,45,94,230,185,113,123,121,73,60,207,250,209,178,21,30,93,47,110,252,18,59,181,149,77,226,113,46,148,175,241,66,113,227,77,236,212,86,74,133,211,252,69,194,55,213, +145,191,8,43,151,178,83,59,25,36,254,227,52,90,198,206,163,197,157,7,177,85,27,73,23,206,114,143,156,165,247,8,75,167,179,85,27,217,37,188,254,55,68,206,210,67,132,215,6,119,177,85,27,17,126,12,184,67,214,214,59,132,31,6,178,85,235,105,47,252,97,42,237, +23,113,165,8,107,183,103,175,150,115,191,240,6,155,14,178,214,238,32,188,133,233,126,246,106,57,147,69,131,220,45,111,239,221,162,222,147,217,171,229,44,21,13,114,182,188,189,103,139,122,47,101,175,150,35,188,18,212,75,222,222,189,184,30,228,77,242,68, +15,221,203,92,92,244,85,6,121,236,213,114,10,4,115,44,146,185,120,145,160,120,1,123,181,156,35,170,206,81,36,247,8,123,181,28,209,237,21,155,101,46,190,89,116,11,11,123,181,156,243,130,57,190,47,115,241,247,5,197,207,179,87,203,17,253,50,176,197,50,23, +95,44,40,94,197,94,45,71,116,127,85,134,204,197,51,68,119,177,177,87,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,16,0,0,0,0,178,37,58,126,216,216,241,205,150,43,130,57,126,54,94,226,124,38,40,126,165,249,106,140,29,22,31,237,229,246, +59,204,200,85,236,87,247,146,203,185,51,188,122,132,46,58,173,140,121,170,152,178,52,79,126,12,196,23,50,74,85,83,232,193,183,84,15,43,101,142,234,166,116,152,219,253,15,168,100,138,42,167,114,128,187,253,155,126,3,38,145,60,46,191,81,117,53,19,84,61, +171,221,236,191,95,136,1,170,158,144,155,223,88,180,150,249,169,159,181,206,247,31,89,206,248,212,79,185,243,175,85,29,206,244,252,144,225,142,1,204,103,120,126,200,124,199,0,222,103,120,126,136,243,7,234,191,96,120,126,200,23,142,1,124,202,240,252,144, +79,29,3,88,206,240,252,144,229,142,1,164,51,60,63,196,249,23,213,223,195,240,252,144,123,156,127,18,84,204,244,212,79,177,139,143,130,151,49,62,245,179,204,5,128,142,85,204,79,245,84,117,116,115,57,112,49,3,84,61,238,190,86,47,122,47,19,84,59,123,93, +222,24,218,177,136,25,170,156,162,142,154,203,244,60,192,20,213,205,129,158,238,111,11,110,189,33,204,32,213,76,120,67,107,79,158,12,73,222,199,44,85,204,190,100,207,158,13,27,184,176,224,124,29,19,85,39,117,231,11,22,14,244,248,241,208,200,46,61,140, +242,147,160,202,214,30,196,69,86,9,70,251,147,225,127,213,165,153,127,185,182,232,125,226,191,120,216,221,77,68,23,100,15,72,211,18,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,8,0,8,0,8,0,8,0,8,0,8,0,8,0,8,0,8,0,8,0,8,0,8,0,8,0,8,0,8,0,8,0, +8,0,8,0,8,0,8,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,176,146,65,139,118,29,58,123,246,208,174,69,131,0,16,64,0,147,78,252,93,242,196,36,0,4,12,64,98,131,206,7,18,1,16,36,0,163,171,27, +246,172,30,13,128,224,0,152,80,127,107,209,250,9,0,8,10,128,193,53,141,53,173,25,12,128,96,0,136,57,217,120,213,147,49,0,8,4,128,116,163,174,233,0,8,2,128,216,10,163,174,21,177,0,8,0,128,23,140,203,190,0,128,0,0,248,210,184,236,151,0,8,0,128,42,227,178, +85,0,240,63,128,88,65,89,61,22,0,190,7,48,64,4,96,0,0,124,15,224,65,17,128,7,1,32,27,128,238,201,227,38,63,158,216,202,187,178,15,137,0,60,228,221,255,167,85,226,227,147,199,37,119,7,128,155,131,19,50,143,221,56,229,210,214,201,49,42,1,136,153,188,245, +210,141,19,143,101,38,0,192,97,238,88,91,119,211,65,197,83,34,84,1,16,49,165,248,166,51,235,214,222,1,0,39,121,246,82,131,163,190,137,83,3,64,220,55,13,78,189,244,44,0,236,39,35,124,235,213,154,4,21,0,36,220,122,173,41,156,1,0,187,73,109,236,176,226, +78,242,3,232,84,220,216,193,169,0,176,151,71,67,141,158,182,39,74,118,0,81,123,26,61,56,244,40,0,236,36,186,200,224,184,84,217,1,164,26,156,92,20,13,0,27,73,51,58,174,180,189,220,0,218,151,26,29,157,6,0,27,255,142,58,103,120,222,107,114,3,120,205,240, +232,115,17,0,176,156,97,198,231,237,147,27,192,62,227,179,135,1,192,114,178,140,207,171,139,147,25,64,92,157,241,217,89,0,176,156,124,193,129,195,101,6,48,92,112,118,62,0,44,167,80,112,96,138,204,0,82,4,103,23,2,192,114,74,5,7,206,147,25,192,60,193,217, +165,0,176,156,106,193,129,25,50,3,200,16,156,93,13,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,0,72,15,160, +74,112,224,34,153,1,44,18,156,93,5,0,203,57,45,56,240,21,153,1,188,34,56,251,52,0,44,231,123,193,129,99,101,6,48,86,112,246,247,0,176,156,45,130,3,239,147,25,192,125,130,179,183,0,192,114,166,27,159,87,22,41,51,128,200,50,227,179,103,1,192,114,58,95, +55,60,239,99,77,102,0,218,199,134,71,215,119,7,128,245,252,219,240,188,199,228,6,240,152,225,209,187,53,0,88,207,64,163,31,1,249,154,220,0,180,124,163,31,0,247,1,192,78,214,52,126,90,104,176,236,0,6,135,26,63,249,19,13,0,118,210,246,112,163,167,165,106, +178,3,208,82,27,61,248,151,88,0,216,75,175,115,141,28,182,70,147,31,64,163,63,188,42,250,105,0,176,153,222,63,53,60,42,188,52,66,5,0,17,75,195,183,252,249,119,186,255,32,3,208,218,174,173,255,199,73,103,199,121,82,182,201,1,104,218,184,179,255,124,255, +247,73,172,6,0,71,111,168,242,254,38,80,177,168,173,166,10,0,173,109,70,197,223,235,223,237,230,179,203,96,3,208,180,174,51,54,255,247,244,133,99,187,87,12,143,242,170,108,115,0,208,180,168,225,43,118,31,187,112,250,251,45,179,186,187,58,39,232,0,154, +32,205,3,192,171,0,192,243,12,17,1,24,10,0,223,3,184,67,4,160,55,0,124,15,32,170,222,184,108,56,6,0,190,7,160,253,230,241,77,59,0,80,12,64,182,113,217,28,0,4,0,192,3,198,101,31,5,64,0,0,104,223,25,117,61,18,1,128,32,0,48,252,36,224,73,13,0,65,0,96,116, +223,214,86,13,0,193,0,208,230,144,151,151,236,1,160,28,0,173,215,255,110,45,90,210,79,3,64,80,0,104,113,255,105,216,115,127,87,13,0,193,1,160,69,189,113,241,31,15,110,46,142,209,0,16,36,0,154,22,151,249,215,71,130,69,217,93,100,109,9,128,166,204,128, +233,75,86,173,90,50,61,81,226,138,0,8,120,0,0,0,0,0,64,118,0,223,9,90,238,96,137,110,178,67,48,218,239,164,105,153,47,104,249,35,75,116,147,31,5,163,205,151,166,229,86,65,203,18,150,232,38,37,130,209,202,115,237,98,131,160,101,109,4,91,116,158,136,90, +193,104,55,72,83,243,67,209,125,150,93,88,163,243,116,17,77,246,67,105,106,102,137,106,222,203,26,157,231,94,209,100,179,164,169,41,250,118,60,125,20,107,116,158,81,122,19,126,99,162,119,73,19,213,156,201,26,157,103,166,104,178,105,210,212,28,35,170, +249,38,107,116,158,55,69,147,29,35,77,205,254,162,154,235,89,163,243,172,23,77,182,191,52,53,163,174,9,106,158,97,141,206,115,70,48,216,107,81,242,244,252,85,4,117,8,123,116,26,225,131,172,191,74,84,116,167,168,232,50,22,233,52,203,68,115,221,41,81,209, +108,81,209,227,44,210,105,142,139,230,154,45,81,209,105,162,162,122,95,54,233,44,125,133,99,157,38,81,211,36,97,211,55,88,165,179,188,33,28,107,146,68,77,35,47,138,154,22,176,74,103,41,16,77,245,98,164,76,85,133,239,2,175,119,102,151,78,34,248,206,116, +201,222,3,106,218,92,225,15,171,84,150,233,36,169,194,161,206,149,170,235,64,97,215,179,109,216,166,253,180,57,43,28,234,64,185,218,150,234,106,92,183,82,40,194,107,172,122,169,100,109,55,11,219,86,243,46,192,254,59,128,106,225,72,55,75,86,119,134,176, +173,132,95,190,35,125,114,196,19,157,33,89,221,184,107,194,186,181,124,24,100,247,67,160,90,225,64,175,197,201,86,120,155,24,236,22,86,106,47,91,196,243,220,38,93,225,177,226,194,225,100,118,106,39,201,97,241,60,199,74,215,56,186,92,220,120,127,20,91, +181,158,168,253,226,105,150,71,203,215,121,165,184,178,254,1,107,181,158,15,76,134,185,82,194,206,67,77,58,235,211,217,171,213,76,55,155,229,80,25,91,255,108,82,250,218,195,108,214,90,30,190,102,50,202,159,165,172,61,213,140,237,133,120,118,107,37,241, +23,204,38,57,85,206,55,46,167,204,122,23,182,99,187,230,105,87,104,54,199,83,146,190,161,158,105,86,92,202,239,226,148,46,91,77,199,40,235,179,54,49,37,166,213,223,102,191,102,121,219,116,136,37,49,178,118,159,99,218,93,223,216,138,21,139,210,106,163, +249,12,231,72,219,190,245,121,243,246,63,116,103,203,198,233,254,131,249,4,207,183,150,183,255,171,230,245,245,51,73,236,217,40,73,103,44,12,240,85,137,95,64,228,65,11,47,224,242,68,54,221,120,38,94,182,48,190,131,145,50,191,132,161,245,22,94,66,120, +41,187,110,44,75,195,22,134,87,63,84,238,23,241,145,110,37,185,119,178,238,134,185,51,215,210,232,62,146,252,101,196,149,89,122,25,87,87,116,100,229,55,167,227,138,171,150,6,87,22,39,251,43,153,166,91,75,229,252,214,172,253,175,127,62,205,175,180,56, +182,105,242,191,152,189,22,95,138,94,242,50,223,32,167,105,154,166,69,188,92,98,117,102,123,21,120,57,61,203,172,190,26,253,232,40,8,104,17,163,142,90,30,88,89,79,21,94,209,136,122,203,47,72,47,93,55,38,208,127,19,180,30,179,174,212,250,180,234,71,168, +241,170,178,116,59,169,217,62,53,46,152,219,143,155,186,189,198,214,168,178,20,121,97,81,5,186,189,212,237,153,55,38,169,91,128,254,58,136,232,150,52,102,222,158,58,155,99,42,80,230,182,74,27,111,3,110,74,232,247,3,185,171,151,204,246,121,150,172,206, +61,240,123,200,201,124,212,120,3,112,35,79,212,234,196,227,212,62,161,210,207,184,148,122,54,230,109,234,83,212,250,91,110,46,43,243,54,115,85,123,159,147,197,206,188,76,150,166,92,214,177,53,239,178,78,193,127,234,68,237,100,111,94,101,167,146,207,213, +69,111,100,115,222,100,99,180,166,102,150,179,59,47,178,92,221,79,188,94,15,179,62,183,9,191,174,242,103,158,47,134,216,160,187,132,94,84,251,83,239,145,213,236,208,77,170,71,170,126,221,163,239,97,182,232,60,135,125,240,221,74,173,86,178,71,167,89,233, +143,231,168,38,84,177,74,39,169,154,224,151,203,223,125,14,177,77,251,57,212,199,63,55,64,68,47,168,97,161,246,82,179,32,90,243,83,122,111,103,167,118,178,189,183,239,110,131,26,89,196,90,173,166,104,164,230,195,180,126,235,10,171,181,146,43,111,249, +245,78,233,174,217,127,176,94,179,252,145,221,85,243,111,58,102,86,178,98,81,42,51,253,254,208,100,135,140,114,214,108,148,242,140,14,154,255,211,38,37,175,142,93,223,154,186,188,148,192,252,106,157,174,233,124,52,212,240,99,159,244,174,90,160,146,184, +236,224,117,214,126,35,215,15,46,75,212,2,152,219,199,229,28,15,252,29,35,225,227,57,227,110,215,130,155,46,147,222,205,253,45,160,207,17,213,254,150,251,238,164,46,26,209,162,18,158,153,191,102,115,94,65,225,169,178,63,253,190,245,63,203,78,21,22,228, +109,94,51,255,153,4,41,110,245,253,63,97,35,250,251,59,171,235,192,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* garbage_png = (const char*) temp_binary_data_7; + +//================== reload.png ================== +static const unsigned char temp_binary_data_8[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,0,0,0,2,0,8,3,0,0,0,195,166,36,200,0,0,0,3,115,66,73,84,8,8,8,219,225,79,224,0,0,0,9,112,72,89,115,0,0,14,121,0,0,14,121,1,98,20,222,69,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119, +119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,3,0,80,76,84,69,255,255,255,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,11,35,183,225,0,0,0,255,116,82,78,83,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, +32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, +112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174, +175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237, +238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,235,8,217,53,0,0,28,35,73,68,65,84,24,25,237,193,7,96,84,85,162,6,224,127,50,73,72,67,122,143,8,72,19,41,10,2,145,34,161,87,11,29,65,93,16,69,16,21,117,215,5,65,81,68,16,148,162,174, +32,32,2,22,144,222,44,232,74,47,42,69,16,233,44,69,154,40,161,12,16,66,218,204,255,118,223,22,27,231,204,220,59,147,228,220,51,231,251,96,40,233,134,33,75,119,167,93,58,182,249,181,214,49,48,194,78,211,13,62,254,215,79,127,137,135,17,86,74,206,231,111, +252,216,4,70,24,169,118,140,191,147,253,12,140,176,113,219,5,254,209,159,97,132,137,66,71,121,13,190,238,48,194,195,98,94,211,133,162,48,194,65,35,10,76,131,17,14,86,82,192,155,8,67,127,55,82,232,25,24,250,235,79,161,29,48,244,183,128,66,217,209,48,180, +183,153,98,85,96,104,111,31,197,218,193,208,222,73,138,245,128,161,189,163,20,123,16,134,246,246,82,108,32,12,237,109,163,216,51,48,180,183,158,98,195,97,104,239,11,138,141,129,17,10,249,203,86,170,118,75,189,134,77,91,117,232,216,253,254,251,187,221, +211,174,197,29,245,111,189,185,82,217,18,81,200,123,75,40,246,6,12,155,220,215,55,234,54,96,216,248,153,203,55,238,253,41,147,34,190,179,123,86,205,153,56,164,119,219,218,165,163,144,71,102,83,236,29,24,22,229,171,216,252,193,17,179,214,30,205,162,69, +190,179,123,86,205,153,56,164,103,173,124,200,93,211,41,246,33,140,128,197,220,114,255,216,79,143,249,24,172,236,3,139,71,246,168,17,141,220,242,38,197,22,195,8,128,187,114,231,23,22,236,207,102,40,101,237,91,56,162,219,205,81,200,121,99,40,246,57,12, +63,138,118,24,189,38,149,57,37,115,207,252,225,247,20,70,142,26,78,177,117,48,196,34,106,62,242,222,65,230,60,223,119,19,239,42,136,28,243,12,197,182,194,184,182,200,6,47,126,121,137,185,199,251,237,184,246,215,33,71,12,164,216,110,24,215,80,254,145, +197,30,230,190,236,45,99,219,36,32,228,250,80,236,8,140,223,201,127,215,91,7,153,119,178,190,26,221,50,14,33,213,131,98,167,97,252,90,197,193,235,50,153,231,50,87,246,43,138,208,185,139,98,23,97,252,79,229,97,59,168,138,172,47,30,44,132,16,105,65,177, +76,24,255,118,211,240,239,169,150,204,79,31,40,128,80,104,72,137,72,24,64,245,17,123,168,162,244,101,189,242,35,104,183,82,34,63,194,94,209,39,191,167,186,174,46,238,30,143,224,84,161,68,9,132,55,119,187,133,25,84,220,149,249,157,99,17,132,178,148,40, +143,112,86,113,244,73,58,130,103,66,5,216,86,148,18,213,16,182,226,123,175,167,115,120,151,183,128,77,113,148,184,13,97,170,236,248,139,116,152,61,253,227,96,135,139,18,141,17,150,234,207,203,166,3,93,24,87,14,54,92,165,88,107,132,159,136,78,27,233,84, +222,165,77,97,217,57,138,221,131,112,147,240,196,97,58,218,174,135,99,97,205,9,138,245,68,120,41,249,170,135,142,119,110,236,13,176,226,32,197,250,34,156,148,152,144,70,45,100,207,190,17,129,251,142,98,143,35,124,20,31,159,70,109,100,189,93,26,129,250, +138,98,127,69,184,40,246,218,21,106,37,109,108,97,4,102,21,197,94,68,120,40,54,54,149,218,241,12,139,71,32,62,166,216,171,8,7,133,198,164,82,75,63,63,17,13,255,230,81,236,111,208,95,212,160,115,204,37,153,94,230,178,31,122,187,225,207,44,138,189,11,237, +221,125,144,57,231,242,241,157,107,151,206,156,48,252,241,251,58,52,172,86,42,22,112,199,22,40,86,186,92,229,234,181,147,238,104,222,246,238,174,189,250,141,120,247,139,221,30,230,160,189,157,224,199,100,138,205,129,230,110,93,205,156,112,225,155,247, +134,118,174,94,52,18,129,73,168,210,252,79,67,39,47,223,254,179,143,57,96,75,11,72,141,163,216,82,104,173,212,12,47,67,43,235,224,199,227,30,110,92,28,54,69,151,111,244,240,148,45,233,12,177,85,181,33,49,146,98,95,64,99,113,195,83,25,58,105,155,222,253, +235,221,85,163,16,2,81,181,30,124,235,235,52,134,80,246,184,56,8,61,75,177,13,208,87,167,19,12,149,75,43,158,109,24,141,208,114,87,127,224,141,13,151,25,42,71,219,64,100,16,197,182,65,87,101,150,48,52,206,45,125,250,54,55,114,72,68,213,158,227,55,101, +51,36,102,23,195,181,245,163,216,94,232,201,53,224,34,67,224,244,188,129,53,92,200,105,133,122,188,127,134,33,112,174,55,174,233,62,138,29,133,150,170,109,100,208,142,189,255,80,101,228,150,136,250,47,109,243,49,104,43,43,226,26,58,81,236,103,104,40, +250,197,12,6,105,239,11,85,145,219,74,246,89,112,145,65,74,27,18,137,63,104,67,177,75,208,79,163,189,12,206,193,151,107,32,111,68,37,191,186,135,193,217,89,15,191,215,132,98,217,208,77,220,36,31,131,113,116,204,173,200,83,229,30,253,60,155,65,240,190, +158,128,223,170,75,137,104,232,165,238,1,6,225,196,248,122,80,64,153,97,135,24,132,99,29,240,27,55,83,162,0,116,226,126,46,139,182,253,248,102,67,23,20,225,74,254,32,141,246,125,84,0,191,82,129,18,165,160,145,10,155,104,215,185,201,201,17,80,74,129,254, +91,104,219,225,58,248,69,73,74,84,128,62,250,92,162,77,251,251,199,66,65,53,38,166,208,166,244,71,241,63,215,81,162,58,116,81,100,17,109,90,217,206,5,69,69,119,93,225,165,61,243,242,227,63,162,40,81,23,154,104,245,35,109,73,159,81,3,74,75,124,238,48, +109,57,120,11,254,35,139,98,77,160,133,136,151,125,180,227,204,136,18,80,158,171,253,102,218,113,181,31,254,237,34,197,218,64,7,69,190,160,29,187,251,198,192,25,90,127,69,59,102,39,224,95,126,162,88,39,104,160,206,15,180,206,183,162,21,28,164,197,122, +218,176,191,58,254,233,8,197,122,193,249,30,188,74,203,174,78,171,6,135,105,186,134,214,165,61,8,96,55,197,30,134,211,229,155,70,203,50,223,44,6,7,106,252,37,173,123,47,14,91,41,54,8,14,87,118,11,45,91,84,9,14,213,224,115,90,182,167,218,58,138,13,129, +179,181,72,161,85,223,52,132,131,213,251,132,86,165,254,72,177,151,224,104,143,101,211,162,195,221,224,112,117,150,49,132,94,131,131,69,76,164,69,231,159,142,134,243,213,223,206,144,153,4,231,138,91,66,107,50,198,23,130,22,220,143,123,24,34,51,224,88, +37,182,208,154,121,21,160,141,146,179,25,26,115,225,84,213,142,210,146,141,245,161,149,102,251,24,10,203,224,80,205,46,208,138,131,157,160,155,232,103,175,48,120,95,194,153,122,103,210,130,236,81,209,208,208,13,203,24,180,141,112,164,23,105,197,254,250, +208,212,157,71,25,164,237,112,162,9,180,192,247,122,44,180,21,55,58,131,65,217,7,231,113,77,162,5,71,147,161,181,170,171,24,140,99,112,156,136,233,180,224,157,252,208,93,207,243,180,47,5,78,227,254,128,129,59,213,22,97,160,236,87,180,45,21,14,19,57,143, +129,155,83,8,97,33,114,140,143,54,121,225,44,209,75,25,176,148,46,8,27,109,206,208,166,124,112,146,152,207,24,176,165,37,16,70,74,175,161,61,133,224,32,113,43,25,40,207,159,16,94,34,94,244,210,142,210,112,142,132,117,12,212,134,235,17,118,154,254,72, +27,42,194,49,10,124,205,64,189,19,133,48,84,236,115,90,87,3,78,81,112,27,3,148,253,4,194,147,107,72,22,173,170,15,135,136,89,207,0,157,111,137,176,213,224,56,45,74,134,51,184,151,48,64,251,43,33,140,21,94,70,107,218,193,25,166,48,64,43,10,32,252,184, +243,23,47,119,83,157,198,173,238,185,183,239,227,7,104,73,23,56,194,11,12,208,120,55,116,229,138,45,146,88,185,214,237,205,59,116,235,61,224,207,207,141,126,125,234,7,11,63,91,187,121,215,161,31,61,25,180,239,126,56,65,63,6,38,163,15,52,224,174,80,175, +73,219,78,247,245,27,244,236,75,227,38,207,156,183,124,229,87,59,14,156,56,155,230,99,78,120,4,14,112,79,54,3,242,115,3,56,157,171,209,219,7,50,153,139,158,132,250,26,93,101,64,118,148,133,211,117,60,200,92,54,20,202,187,249,60,3,178,32,14,14,151,184, +138,185,110,36,84,119,253,9,6,194,247,162,11,14,87,243,36,115,223,120,40,174,240,30,6,34,163,43,156,174,198,69,230,129,201,80,91,236,38,6,226,106,27,56,93,194,126,230,133,89,80,154,107,9,3,145,218,12,142,55,157,121,98,30,148,54,140,129,184,212,24,142, +87,37,155,121,226,99,168,172,149,151,1,184,80,31,206,247,1,243,198,74,40,172,220,57,6,224,108,109,56,95,204,85,230,141,181,80,87,204,183,12,192,207,53,160,129,150,204,35,171,160,174,25,12,192,169,170,208,193,40,230,145,185,80,214,35,12,192,241,138,208, +194,116,230,145,55,160,170,122,25,244,239,72,57,232,97,62,243,200,99,80,84,177,19,244,239,248,245,208,196,50,230,145,10,80,147,123,53,253,59,87,13,186,120,139,121,99,55,20,245,42,253,75,107,8,109,60,197,188,241,32,212,212,133,254,101,223,5,125,52,97, +158,216,235,134,146,170,94,162,127,15,67,35,17,39,153,7,178,155,66,73,145,91,233,223,112,104,229,53,230,129,103,160,166,225,244,111,10,244,82,226,34,115,221,27,80,83,237,76,250,181,196,13,205,252,133,185,44,123,32,212,148,111,55,253,218,16,3,221,68,173, +97,174,218,120,43,20,53,150,126,237,46,4,253,20,218,207,92,147,190,172,51,84,213,208,75,127,126,76,132,142,18,183,50,231,120,83,207,28,219,183,125,227,151,203,230,206,24,247,104,235,235,160,172,184,127,208,159,204,6,208,83,204,187,12,142,239,74,202,241, +253,59,54,173,92,62,111,230,228,113,35,159,29,212,239,190,206,109,147,235,213,184,177,116,193,124,112,138,73,244,107,32,180,85,231,51,250,229,75,59,123,226,192,119,95,173,250,120,254,172,183,199,191,60,244,169,71,238,239,210,174,105,253,154,21,203,20, +138,129,243,181,240,209,159,247,161,179,10,79,254,253,200,85,146,87,207,157,60,184,243,235,213,159,44,120,111,202,132,81,195,158,238,255,64,215,246,205,146,106,85,74,44,28,235,130,198,10,28,167,63,59,98,161,189,252,113,46,132,167,89,244,231,124,121,24, +218,186,139,254,120,219,194,208,86,225,159,232,207,243,48,244,245,22,253,89,238,130,161,173,154,217,244,227,31,5,96,232,107,45,253,72,173,14,67,95,221,233,207,3,48,244,21,119,156,126,44,134,161,177,145,244,227,76,49,24,250,42,127,149,126,116,132,161, +177,37,244,227,125,24,26,107,73,63,78,22,132,161,175,168,189,244,163,21,12,141,61,77,63,222,134,161,177,18,23,41,119,56,30,134,198,102,80,206,219,24,134,198,170,121,41,55,14,134,206,230,82,110,95,12,12,141,221,236,165,92,11,24,58,155,79,185,69,48,116, +86,221,71,169,180,27,96,232,108,1,229,94,128,161,179,26,62,74,29,141,129,161,179,133,148,235,8,67,103,53,125,148,250,59,12,173,45,162,84,230,77,48,116,86,203,71,169,241,48,180,182,152,82,167,175,131,161,179,91,124,148,250,19,12,173,45,161,212,54,23,12, +157,85,240,82,170,3,12,173,141,163,212,86,24,90,139,61,79,169,14,48,180,214,151,82,91,97,232,109,7,165,58,192,208,90,67,74,109,133,161,183,57,148,234,0,67,107,37,51,41,179,21,134,222,134,83,170,3,12,173,69,158,162,204,86,24,122,235,74,169,14,48,244,182, +142,50,219,97,232,173,6,165,250,192,208,219,20,202,156,141,129,161,181,124,23,41,243,42,12,189,117,164,140,183,60,12,189,205,163,204,199,48,244,22,127,133,50,173,97,232,237,94,202,28,116,193,208,219,82,202,60,9,67,111,5,210,41,145,90,16,134,222,122,83, +102,42,12,205,125,78,153,154,48,244,86,52,139,18,235,97,104,174,63,101,250,192,208,220,90,74,164,23,128,161,183,210,94,74,44,133,161,185,39,41,211,3,134,230,54,81,226,74,60,12,189,21,202,166,196,71,48,52,215,153,50,119,195,208,220,84,74,120,242,193,208, +220,81,74,204,132,161,185,74,148,105,5,67,115,3,41,113,38,18,134,230,150,81,98,50,12,205,69,94,162,196,29,48,52,215,152,18,30,55,12,21,21,111,216,169,85,253,66,8,133,145,148,88,12,67,61,13,38,159,225,191,120,55,191,80,2,65,219,76,137,1,48,84,115,219, +22,254,34,237,205,162,8,78,33,47,37,42,194,80,75,228,235,94,254,198,169,38,8,74,23,74,28,133,161,150,184,79,248,123,217,253,17,140,105,148,152,6,67,41,145,235,248,71,222,110,8,194,97,74,116,129,161,148,87,120,45,25,181,97,91,97,74,120,11,195,80,201,29, +62,94,211,102,23,236,106,73,137,45,48,148,178,150,2,125,97,215,16,74,140,130,161,146,198,20,249,14,118,45,164,68,50,12,149,188,77,161,234,176,233,40,197,82,163,97,168,228,32,133,70,192,158,34,148,248,20,134,74,74,82,236,11,216,211,138,18,207,193,80,73, +77,138,157,131,61,207,82,162,13,12,149,52,162,196,141,176,101,17,37,138,193,80,73,99,74,244,128,45,63,80,236,7,24,74,41,77,137,241,176,163,40,37,22,193,80,75,42,197,214,195,142,214,148,120,22,134,90,182,80,44,53,2,54,12,165,68,75,24,106,153,76,137,155, +97,195,98,74,20,134,161,150,62,148,232,13,27,142,82,236,48,12,197,84,167,196,36,88,23,229,165,216,124,24,138,113,167,82,108,11,172,171,72,137,191,194,80,205,6,138,165,71,195,178,86,148,104,6,67,53,19,41,81,7,150,245,167,152,175,0,12,213,244,164,68,127, +88,246,42,197,142,195,80,78,37,74,188,11,203,22,82,108,45,12,229,184,46,80,108,51,44,219,78,177,25,48,212,179,146,98,103,97,153,135,98,207,193,80,207,24,74,20,128,69,133,41,209,19,134,122,58,83,226,86,88,116,27,37,146,96,168,231,6,74,116,129,69,221,40, +81,28,134,130,174,80,108,48,44,26,66,177,84,24,42,218,69,177,105,176,104,26,197,190,135,161,162,165,20,91,5,139,86,82,108,41,12,21,141,167,216,81,88,116,132,98,19,96,168,232,81,138,101,71,193,154,84,138,61,6,67,69,173,41,81,9,150,68,81,162,29,12,21,85, +164,68,27,88,82,156,18,213,96,168,40,42,155,98,3,97,73,21,74,148,128,161,164,35,20,155,0,75,146,40,17,13,67,73,95,82,108,41,44,105,75,177,43,48,212,52,133,98,223,195,146,158,20,59,9,67,77,207,80,236,52,44,25,72,177,93,48,212,212,137,98,25,176,228,57, +138,173,135,161,166,218,148,136,135,21,227,41,182,12,134,154,174,167,196,245,176,98,6,197,102,193,80,83,60,37,106,193,138,37,20,155,0,67,81,25,20,107,10,43,214,81,236,121,24,138,58,77,177,206,176,226,123,138,61,6,67,81,123,40,246,48,172,56,65,177,94, +48,20,181,129,98,131,97,197,5,138,181,131,161,168,101,20,27,3,43,60,20,75,134,161,168,153,20,155,6,43,60,20,75,134,161,168,241,20,91,8,43,60,20,107,10,67,81,195,40,182,26,86,120,40,214,20,134,162,6,80,236,59,88,225,161,88,51,24,138,234,78,177,227,176, +194,67,177,230,48,20,213,130,98,23,96,133,135,98,205,97,40,42,137,98,30,88,225,161,88,11,24,138,74,162,152,7,86,120,40,214,2,134,162,146,40,230,129,21,30,138,181,132,161,168,36,138,121,96,133,135,98,173,96,40,42,137,98,30,88,225,161,88,43,24,138,74,162, +152,7,86,120,40,214,26,134,162,146,40,230,129,21,30,138,181,129,161,168,36,138,121,96,197,5,138,117,129,161,168,36,138,121,96,197,9,138,245,131,161,168,36,138,121,96,197,78,138,13,134,161,168,36,138,121,96,197,26,138,141,133,161,168,36,138,121,96,197, +34,138,77,131,161,168,36,138,121,96,197,59,20,91,8,67,81,73,20,243,192,138,177,20,91,5,67,81,205,40,118,1,86,12,166,216,14,24,138,234,76,177,147,176,226,97,138,253,0,67,81,15,81,108,23,172,232,66,177,75,48,20,245,12,197,214,195,138,102,148,136,132,161, +166,209,20,91,6,43,110,161,68,49,24,106,122,155,98,179,96,69,89,74,84,134,161,166,185,20,155,0,43,18,40,209,0,134,154,190,160,216,243,176,36,131,98,61,97,168,105,43,197,30,131,37,63,81,236,57,24,106,58,68,177,94,176,100,23,197,102,194,80,211,57,138,181, +131,37,203,40,182,14,134,146,92,217,20,187,29,150,76,164,216,73,24,74,42,64,137,170,176,228,49,138,249,98,96,168,168,2,37,74,192,146,182,148,168,10,67,69,205,40,17,13,75,42,83,162,61,12,21,61,68,177,43,176,38,218,75,177,199,97,168,104,52,197,142,194, +162,99,20,123,29,134,138,230,82,108,53,44,90,77,177,229,48,84,180,133,98,211,97,209,59,20,219,13,67,69,103,41,54,20,22,13,161,88,154,11,134,122,174,163,68,15,88,212,149,18,55,192,80,79,45,74,212,131,69,181,41,209,25,134,122,58,82,162,40,44,42,72,137, +87,96,168,231,207,20,187,4,203,206,81,108,37,12,245,76,162,216,119,176,108,11,197,46,184,96,40,103,5,197,22,195,178,153,148,168,4,67,57,7,40,54,14,150,61,74,137,158,48,84,19,155,69,177,129,176,172,46,37,38,194,80,77,18,37,218,194,178,232,12,138,109,128, +161,154,199,40,81,5,214,109,165,88,170,27,134,98,102,81,204,155,15,214,77,166,68,117,24,138,217,77,177,99,176,161,15,37,250,192,80,75,124,54,197,150,193,134,234,148,152,12,67,45,13,41,241,60,108,112,167,82,108,11,12,181,12,162,68,59,216,177,158,98,169, +48,212,242,1,37,74,192,142,241,148,40,13,67,41,251,40,118,2,182,244,160,68,99,24,42,201,239,165,216,82,216,114,35,37,26,193,80,201,29,148,120,14,246,156,167,88,77,24,42,121,154,18,109,97,207,23,20,43,5,67,37,11,40,81,28,246,188,72,161,67,48,84,18,113, +158,98,199,97,211,13,217,20,153,10,67,37,245,40,177,4,118,45,166,72,50,12,149,12,163,196,48,216,149,76,129,141,48,148,178,150,18,109,96,219,247,188,38,95,51,24,42,73,200,164,68,49,216,86,247,50,175,229,53,24,74,105,79,137,31,16,132,230,233,252,163,117, +145,48,148,242,6,37,102,34,24,157,178,249,123,159,199,195,80,203,94,74,220,139,160,116,62,201,223,240,77,137,130,161,150,68,74,248,138,34,56,177,131,47,240,23,223,53,128,161,154,62,148,216,134,160,21,26,185,230,12,255,229,204,212,228,8,24,202,153,67, +137,209,8,137,226,205,186,220,86,24,134,138,92,103,40,145,12,67,115,245,40,145,26,13,67,115,19,40,241,9,12,205,185,78,82,226,9,24,154,187,131,50,85,97,104,110,50,37,142,195,208,156,251,12,37,166,195,208,92,43,202,116,131,161,185,25,148,240,22,134,161, +183,232,11,148,248,6,134,230,238,162,204,211,48,52,55,135,18,190,68,24,122,139,75,165,196,6,24,154,235,70,153,129,48,52,183,130,18,217,197,97,232,173,162,143,18,95,194,208,220,4,202,244,133,161,183,184,11,148,200,44,4,67,111,253,40,243,49,12,205,237, +164,76,47,24,122,107,76,153,180,252,48,244,54,143,50,11,96,232,173,116,22,101,186,192,208,219,8,202,92,142,133,161,181,168,211,148,153,14,67,111,61,40,117,11,12,189,125,69,153,77,48,244,214,130,82,247,194,208,219,38,202,252,20,13,67,107,45,41,53,18,134, +222,190,162,76,86,25,24,90,107,77,169,133,48,244,246,53,165,146,97,104,173,13,165,118,195,208,219,55,148,26,0,67,107,109,41,117,49,1,134,214,182,80,234,77,24,90,107,79,185,170,48,116,230,218,74,169,207,96,104,237,1,202,213,135,161,179,252,167,41,245, +25,12,173,189,70,185,186,48,116,86,37,147,82,159,192,208,218,10,202,221,6,67,103,119,82,110,57,12,157,229,59,68,185,218,48,116,54,148,114,75,97,232,172,76,42,165,124,183,194,208,217,28,202,45,129,161,179,198,148,243,213,130,161,177,168,157,148,91,4,67, +103,47,83,206,87,19,134,198,234,101,83,238,125,24,26,139,221,79,185,203,165,96,104,236,117,250,241,87,24,26,75,246,81,238,96,52,12,125,229,255,129,126,180,131,161,177,233,244,227,19,24,26,107,79,63,50,42,194,208,87,225,211,244,99,12,12,141,205,165,31, +167,18,96,232,171,7,253,233,5,67,95,85,47,209,143,141,48,244,149,127,31,253,240,214,70,56,113,21,190,41,185,251,19,35,199,140,121,177,99,34,194,192,34,250,51,21,250,139,40,94,163,69,175,167,199,206,90,177,253,84,38,127,177,123,64,60,52,55,152,254,164, +20,133,166,34,75,221,210,250,129,103,198,125,240,247,157,63,101,83,224,92,79,104,173,121,54,253,233,2,173,68,39,214,105,215,103,200,196,57,171,118,167,248,24,136,133,9,208,87,217,20,250,51,27,26,136,45,87,255,206,135,134,189,57,111,237,190,243,180,108, +67,2,116,149,111,43,253,57,85,8,78,149,112,99,131,142,253,95,152,188,104,227,63,46,49,40,235,34,161,169,233,244,171,45,156,165,64,229,198,93,6,190,52,117,233,215,71,174,48,100,134,65,79,15,211,175,105,112,0,87,225,155,146,187,63,49,106,250,199,91,142, +165,51,39,164,223,4,29,213,77,167,63,71,19,160,172,136,42,45,122,61,61,118,214,103,223,158,204,100,78,155,5,13,149,60,78,127,124,77,160,168,18,67,215,93,102,238,185,90,4,218,185,110,7,253,154,8,53,149,249,48,131,185,107,0,116,19,189,138,126,237,139,133, +146,30,242,48,183,189,11,205,184,230,210,175,236,122,80,210,68,230,190,111,161,153,55,232,223,203,80,210,4,230,129,243,208,203,96,250,183,35,10,42,234,197,188,224,129,86,30,160,127,87,110,134,138,18,47,48,47,120,160,147,182,89,244,239,94,40,105,22,243, +196,1,104,164,94,42,253,123,29,74,42,158,206,60,241,30,244,81,41,133,254,109,136,132,146,134,48,111,244,135,54,74,29,161,127,63,150,132,154,86,48,79,164,23,131,46,18,15,208,191,204,134,80,212,89,230,137,247,161,139,114,71,24,128,199,161,168,226,204,19, +153,53,160,137,74,39,24,128,15,161,170,50,204,19,195,160,137,106,167,25,128,157,113,80,85,89,230,133,53,110,232,161,214,25,6,224,194,141,80,86,73,230,129,181,241,208,67,221,243,12,128,175,3,212,229,246,50,215,45,136,131,30,26,94,100,32,70,64,101,103, +152,203,82,186,67,19,77,83,25,136,79,34,160,178,93,204,85,223,247,79,128,38,218,164,49,16,155,227,161,180,149,204,21,190,179,123,86,127,244,74,151,242,208,70,215,12,6,226,64,81,168,109,54,115,142,247,204,174,149,179,39,12,238,221,182,118,153,40,232,197, +53,194,199,64,252,88,14,138,155,192,16,203,62,253,221,23,239,191,246,151,251,91,213,42,233,134,174,226,23,51,32,158,154,80,221,96,134,66,230,169,237,43,102,141,121,170,103,243,234,197,34,160,191,114,59,25,144,244,38,80,94,111,218,150,113,124,235,39,239, +142,30,212,163,105,181,34,46,132,147,38,41,12,136,183,51,212,215,150,214,164,29,253,102,217,180,145,143,117,189,163,74,65,132,169,254,153,12,204,0,56,64,109,90,113,181,59,194,93,228,100,6,232,37,56,65,25,90,226,27,229,70,88,43,178,134,1,154,6,71,136, +242,209,154,53,37,17,198,106,28,97,128,150,186,225,12,103,105,209,233,166,8,91,247,92,102,128,54,196,192,33,246,208,170,236,97,46,132,167,231,124,12,208,182,130,112,138,213,180,110,69,17,132,161,184,249,12,212,215,5,224,24,31,209,134,227,183,35,236,148, +221,206,64,173,207,15,231,120,157,118,100,62,133,48,211,219,195,64,173,138,135,131,60,75,123,22,23,64,24,41,249,49,3,246,121,44,156,228,65,218,116,248,86,132,141,123,207,49,96,31,231,131,163,180,167,93,233,143,32,60,20,91,200,192,45,138,130,179,220,70, +251,150,93,143,48,208,249,12,3,247,81,36,28,230,122,6,225,242,147,110,104,174,240,28,90,240,158,27,78,19,205,160,124,91,7,90,235,240,35,45,120,39,2,206,115,129,65,201,126,61,1,218,42,48,147,86,76,114,193,129,246,51,72,39,238,129,166,90,157,160,21,163, +225,72,107,25,180,37,137,208,80,194,84,90,113,181,23,156,105,30,131,119,121,144,27,186,105,123,148,86,156,170,7,135,122,147,161,176,173,54,180,82,103,21,45,217,82,26,78,53,140,33,145,61,49,1,218,40,63,219,71,75,62,140,129,99,61,196,16,57,222,213,5,45, +20,153,144,65,75,188,131,225,96,119,50,100,118,220,5,231,139,25,236,161,53,151,58,192,201,234,49,132,182,182,133,179,69,244,62,65,139,14,85,131,163,221,192,144,250,170,5,28,172,237,247,180,106,85,97,56,91,12,37,134,29,160,101,235,154,192,161,234,172, +162,101,127,139,132,211,93,164,216,131,9,179,105,221,202,6,112,160,242,115,124,180,42,179,31,156,239,32,197,158,5,30,74,163,117,43,234,194,97,18,39,102,208,178,148,59,160,129,13,20,155,8,160,250,94,218,176,252,86,56,72,195,249,89,180,110,103,57,232,96, +33,197,230,224,159,226,223,163,13,190,69,183,193,25,162,31,216,70,59,22,199,67,11,147,40,182,10,255,175,247,21,218,177,237,161,120,40,175,228,136,159,105,199,213,167,92,208,195,112,138,237,194,191,221,180,155,182,92,156,84,3,74,171,251,97,38,109,217, +122,19,116,209,143,98,103,240,31,177,211,105,211,166,251,99,160,168,168,30,95,211,158,204,225,145,208,198,221,20,243,186,241,95,189,46,211,166,115,19,170,64,65,197,134,157,162,77,187,107,67,35,73,148,40,129,255,169,178,147,182,173,238,30,5,181,220,50, +35,157,54,121,95,203,7,157,148,167,68,77,252,34,102,10,237,251,249,149,242,80,70,181,231,119,210,182,195,141,160,151,56,74,180,192,175,181,60,76,251,124,95,14,40,3,5,220,250,242,62,6,97,74,60,116,115,153,98,189,240,27,177,99,178,24,4,223,214,231,106, +32,47,185,234,191,122,152,193,56,217,26,250,57,68,177,167,241,59,53,55,51,56,71,94,111,26,137,60,17,209,248,141,19,12,206,135,133,160,161,77,20,27,131,223,139,120,252,18,131,116,254,131,174,249,145,203,34,91,188,253,19,131,148,210,25,90,90,76,177,153, +248,163,196,165,12,90,198,138,254,101,144,107,10,221,249,238,89,6,109,89,9,232,233,109,138,125,134,107,233,116,138,193,243,109,125,169,93,81,228,184,202,189,167,237,241,49,120,23,123,67,87,47,82,108,27,174,233,186,73,94,134,196,161,217,79,212,139,70, +14,137,105,52,120,89,10,67,194,247,65,34,180,53,128,98,39,32,112,251,46,134,74,250,55,111,220,91,1,33,86,170,243,248,111,50,24,42,171,107,67,99,157,40,150,1,145,168,161,87,25,66,41,159,60,223,178,32,66,34,127,237,71,63,60,194,16,218,211,30,90,107,72, +137,130,16,170,248,41,67,203,119,232,239,83,135,116,175,87,28,246,68,92,223,164,207,203,115,190,73,97,104,157,238,231,134,222,110,164,68,21,72,52,90,207,156,144,186,251,227,55,159,234,120,75,1,4,40,174,250,93,79,253,237,211,253,233,204,1,87,70,36,64, +119,9,148,104,12,169,182,219,153,115,206,127,187,120,230,91,99,95,248,203,163,127,234,218,46,185,238,205,229,138,197,187,0,87,124,241,10,53,110,111,113,119,175,126,79,61,63,230,173,153,243,63,251,234,52,115,140,119,122,105,132,129,43,20,235,2,57,87,183, +253,204,69,105,169,62,230,158,207,107,32,44,28,161,216,64,248,227,238,123,156,90,250,174,37,194,196,215,20,27,1,255,242,61,121,134,218,57,217,59,2,225,98,41,197,166,32,16,9,207,123,168,149,75,195,98,17,62,166,82,108,9,2,83,120,108,26,181,113,105,98,113, +132,147,151,40,182,9,129,42,61,57,147,90,56,250,212,117,8,47,3,41,118,8,129,75,28,149,66,199,219,208,201,141,112,211,133,98,151,96,69,76,159,237,116,178,204,15,235,32,12,53,166,68,44,172,105,52,63,139,14,117,118,84,105,132,165,202,148,40,7,171,18,71, +165,208,129,246,244,139,69,152,42,64,137,122,176,46,166,207,118,58,139,111,69,43,132,177,171,20,187,19,182,52,154,159,69,199,72,155,114,19,194,218,49,138,61,4,155,18,71,165,208,17,78,62,91,24,97,110,51,197,134,194,182,152,206,115,83,169,184,51,83,154, +185,17,246,150,83,236,13,4,35,174,203,252,43,84,214,153,41,205,221,48,128,119,40,246,17,130,20,223,109,97,26,21,116,102,106,115,55,140,255,247,50,197,86,35,120,9,61,22,95,165,82,82,166,54,119,195,248,175,199,41,182,7,33,145,191,231,210,116,42,34,101, +106,11,55,140,95,233,70,177,20,132,202,117,247,45,191,202,60,151,50,173,133,27,198,111,53,161,152,47,18,161,19,147,60,98,125,6,243,206,193,169,45,35,97,252,65,85,74,148,66,104,197,54,127,121,83,38,115,93,214,214,137,157,74,192,184,166,66,148,168,133, +208,139,111,245,202,215,89,204,53,151,191,124,161,121,60,12,177,12,138,181,66,206,72,104,59,118,75,54,115,220,233,133,79,214,113,195,144,59,65,177,251,144,115,174,107,255,252,188,221,153,204,41,251,167,247,174,8,35,0,219,40,246,103,228,176,168,155,187, +141,88,180,63,155,161,116,113,251,130,209,29,139,193,8,208,167,20,123,21,185,34,95,173,158,163,150,29,242,50,72,63,109,122,127,120,175,164,98,48,44,153,65,177,89,200,69,177,117,30,120,254,173,5,235,15,120,104,145,247,135,149,83,255,218,169,86,2,12,59, +70,83,108,5,242,66,190,178,117,59,244,29,250,198,220,53,123,206,250,120,45,233,231,142,237,217,188,106,217,236,169,227,71,60,211,191,93,229,104,24,65,24,68,177,237,200,99,81,37,110,168,92,163,78,131,166,109,238,238,122,95,223,190,61,58,36,223,86,53,177, +96,36,140,16,234,65,177,147,48,180,215,148,98,153,48,180,87,141,18,133,97,232,174,8,37,170,194,208,157,43,139,98,141,96,104,239,20,197,146,97,104,111,59,197,146,97,104,111,49,197,234,193,208,222,8,10,101,198,192,208,94,103,10,109,129,161,191,132,203, +20,121,1,70,24,120,135,2,153,165,96,132,129,42,169,188,182,15,97,132,133,251,120,77,41,37,96,132,135,169,188,150,78,48,194,68,204,118,254,209,19,48,194,70,217,245,252,157,236,1,48,194,136,235,225,11,252,181,61,245,96,132,151,18,115,249,63,251,7,229,131, +17,118,42,13,250,116,207,185,140,147,159,140,104,234,130,161,154,255,3,196,114,3,2,196,188,231,130,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* reload_png = (const char*) temp_binary_data_8; + +//================== settings.png ================== +static const unsigned char temp_binary_data_9[] = +{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,0,0,0,2,0,8,3,0,0,0,195,166,36,200,0,0,0,3,115,66,73,84,8,8,8,219,225,79,224,0,0,0,9,112,72,89,115,0,0,14,206,0,0,14,206,1,206,95,197,247,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,119,119, +119,46,105,110,107,115,99,97,112,101,46,111,114,103,155,238,60,26,0,0,3,0,80,76,84,69,255,255,255,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,11,35,183,225,0,0,0,255,116,82,78,83,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, +32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, +112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174, +175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237, +238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,235,8,217,53,0,0,44,98,73,68,65,84,24,25,237,193,7,152,20,101,218,54,208,187,39,49,67,206,8,12,208,32,72,86,28,64,80,137,138,153,96,4,86,193,4,42,234,138,174,74,18,211,138,138,40,210, +141,17,97,5,9,138,160,34,32,146,77,160,172,74,144,69,201,193,86,201,97,24,96,242,76,247,253,255,126,110,48,192,83,213,85,111,85,189,227,85,231,224,79,175,193,29,227,222,92,182,97,127,49,227,16,61,248,221,71,51,195,247,52,129,175,100,43,127,229,43,59, +104,195,143,255,232,93,25,190,146,170,222,139,185,180,173,240,245,51,224,43,137,154,77,45,162,18,209,217,103,195,87,210,84,121,59,70,117,230,213,132,175,68,185,104,47,149,58,124,21,124,37,71,169,231,99,84,237,31,101,225,43,33,106,175,167,3,182,55,129, +175,68,168,181,141,142,216,219,24,190,18,160,230,86,58,100,79,35,248,180,87,115,11,29,179,187,33,124,154,43,189,145,14,250,169,42,124,122,123,149,142,122,15,62,173,93,65,135,221,4,159,198,170,237,167,195,142,213,131,79,95,243,232,184,79,3,240,233,170, +35,93,208,3,62,93,45,160,11,62,135,79,83,205,99,116,195,121,240,233,105,42,93,49,15,62,45,165,23,210,21,177,166,240,233,232,94,186,228,49,248,116,52,159,46,89,1,159,134,18,143,209,37,133,101,224,211,79,123,186,230,82,248,244,51,146,174,121,14,62,253, +44,165,107,190,134,79,63,251,232,154,156,0,124,186,169,66,89,228,203,56,124,93,64,81,3,248,116,211,137,146,237,231,34,46,149,71,81,210,3,62,221,220,69,201,149,136,83,194,58,10,134,195,167,155,151,41,216,143,184,13,162,96,6,124,186,249,140,130,101,136, +91,7,10,190,129,79,55,135,41,8,35,110,149,40,200,75,132,79,47,167,81,50,16,241,219,75,65,35,248,244,210,141,146,246,136,223,50,10,174,130,79,47,247,82,82,30,241,11,83,240,48,124,122,153,68,193,15,176,224,54,10,102,194,167,151,85,20,124,8,11,206,163,96, +3,124,122,57,70,193,179,176,160,2,5,5,73,240,233,164,14,37,55,194,138,221,20,52,133,79,39,151,81,146,1,43,150,80,112,45,124,58,121,144,130,104,26,172,24,71,193,99,240,233,228,13,10,182,195,146,1,20,204,134,79,39,171,41,120,31,150,180,167,96,19,124,26, +73,200,161,224,73,88,82,142,130,162,20,248,244,113,58,37,125,97,205,143,20,180,128,79,31,61,41,105,1,107,22,82,208,7,62,125,60,68,65,81,10,172,121,142,130,81,240,233,227,77,10,54,194,162,155,41,152,3,229,2,21,79,111,151,81,51,17,127,86,41,245,218,95, +125,247,83,19,159,31,113,219,213,237,75,65,169,127,81,48,11,22,181,165,96,43,84,170,120,217,83,159,30,40,226,207,162,251,215,47,30,219,49,17,127,50,77,135,174,44,230,255,228,175,120,250,178,50,80,37,49,159,130,71,97,81,217,24,79,173,56,21,170,84,186, +127,125,140,191,115,104,202,149,165,241,167,209,113,220,14,254,209,241,87,207,130,26,77,40,185,26,86,125,79,65,43,168,209,118,114,46,79,42,239,213,154,248,83,104,255,41,79,101,85,191,4,40,112,13,37,103,192,170,5,20,220,0,21,26,45,225,169,229,60,93,1, +37,94,211,57,148,172,57,7,246,61,70,65,94,34,172,26,67,193,211,176,47,245,241,124,138,142,60,152,138,18,173,234,63,138,41,139,190,86,25,118,205,166,224,27,88,118,35,5,243,96,219,133,59,104,104,75,99,148,96,205,118,210,216,161,171,97,211,38,10,166,195, +178,214,20,236,128,77,41,207,199,104,66,214,165,40,177,46,59,70,83,38,150,134,29,41,69,20,12,135,101,165,99,60,181,104,105,216,210,108,61,205,137,62,136,18,234,222,98,154,180,185,21,108,104,73,73,119,88,183,147,130,214,176,227,238,92,154,54,173,20,74, +160,196,215,104,94,254,125,1,88,246,23,74,130,176,110,62,5,55,194,186,234,11,24,143,143,74,163,196,73,124,147,113,89,84,29,86,61,73,193,137,0,172,27,77,193,24,88,118,249,126,198,231,163,52,148,48,137,111,50,78,251,47,133,69,115,41,248,10,54,244,163,96, +33,44,74,125,145,113,251,40,13,37,74,226,91,140,91,108,92,10,172,40,243,61,5,175,195,134,179,41,89,247,96,109,88,112,230,119,180,224,163,52,148,32,137,51,105,197,55,77,16,175,132,110,211,178,41,185,31,54,164,70,41,138,126,60,176,34,226,19,184,47,159, +150,124,148,134,18,35,113,38,173,201,185,13,113,105,246,204,110,26,184,24,118,108,167,145,252,57,215,166,194,188,154,75,104,213,242,52,148,16,137,111,211,178,119,43,193,172,106,131,215,208,88,45,216,241,62,77,56,54,249,194,4,152,211,235,16,173,91,158, +134,18,33,105,22,109,248,177,19,204,40,117,221,7,69,52,33,19,182,60,73,115,246,142,107,13,99,165,39,208,150,229,105,40,1,146,102,209,150,232,168,36,24,57,255,181,163,52,103,37,108,249,11,77,219,242,104,67,200,50,182,208,166,229,105,208,94,210,108,218, +245,207,250,144,52,120,108,7,77,123,21,182,156,201,120,124,117,91,41,156,82,194,208,66,218,182,60,13,154,75,154,77,251,142,93,143,83,9,116,255,140,241,248,43,108,41,85,204,184,236,29,82,14,39,151,254,49,85,88,150,6,173,37,189,67,37,166,150,195,201,36, +244,253,23,227,211,5,246,108,97,156,142,62,89,29,39,113,109,38,213,88,150,6,141,37,189,75,69,118,156,131,63,72,30,176,141,241,170,10,123,222,99,220,114,95,10,226,119,202,78,166,50,203,210,160,173,164,119,169,76,225,240,4,252,70,233,193,63,49,110,7,96, +211,19,180,160,104,122,11,252,218,57,219,169,208,178,52,104,42,249,61,170,244,81,109,252,79,133,17,7,105,193,71,176,169,15,45,137,125,112,30,254,35,241,225,34,42,181,44,13,90,74,126,143,106,29,238,133,127,171,246,84,22,45,25,15,155,90,208,170,21,151, +227,255,212,91,73,213,150,165,65,67,201,115,168,220,43,105,248,255,210,195,57,180,232,118,216,148,82,64,203,214,255,37,17,184,62,139,234,45,77,133,118,146,223,167,3,54,182,68,195,73,5,180,44,3,118,45,166,13,59,239,154,65,71,44,77,133,102,146,223,167, +35,242,62,44,166,117,63,192,182,59,168,165,165,169,208,74,242,92,234,104,28,108,171,17,165,123,14,79,158,86,72,115,150,166,66,35,201,115,105,78,241,243,61,159,61,64,215,156,15,251,62,163,91,98,99,83,128,102,17,154,179,52,21,218,72,153,71,115,114,46,4, +80,117,30,93,178,62,0,251,206,46,164,59,246,93,140,159,5,35,52,103,73,42,52,145,50,159,230,228,116,197,255,25,148,75,55,228,183,132,10,35,233,138,5,213,240,139,96,132,230,44,73,133,22,82,230,211,156,156,174,248,183,38,235,232,130,7,161,68,226,63,233, +188,188,123,240,95,193,8,205,89,146,10,13,164,124,64,115,114,186,226,191,82,158,139,209,105,75,18,160,70,250,55,116,218,119,45,241,43,193,8,205,89,146,10,207,165,124,64,115,114,186,226,215,186,237,161,179,38,37,67,149,210,239,208,89,47,167,225,55,130, +17,154,179,36,21,30,75,89,64,115,114,186,226,183,170,188,79,7,21,221,3,133,2,143,230,211,57,135,122,226,247,130,17,154,179,36,21,158,42,245,33,205,201,233,138,63,184,45,135,14,41,158,211,14,106,85,29,186,147,14,89,94,11,127,20,140,208,156,197,169,240, +80,169,15,105,78,78,23,156,68,227,181,116,194,145,103,235,65,189,192,37,175,253,68,245,10,135,6,112,50,193,8,205,89,156,10,207,148,90,72,115,114,186,224,164,146,199,68,169,216,182,231,187,36,193,41,103,14,95,81,76,165,182,181,193,41,4,35,52,103,113,42, +60,82,106,33,205,201,233,130,83,185,96,55,213,41,254,236,193,198,112,88,197,62,83,15,80,153,41,101,113,74,193,8,205,89,156,10,79,148,90,68,115,114,186,224,212,42,191,75,53,142,206,188,190,18,92,17,104,251,216,106,170,144,213,7,146,96,132,230,44,46,5, +15,36,45,162,57,57,93,32,26,144,77,219,178,38,116,77,130,155,26,141,138,208,174,207,235,65,22,140,208,156,153,240,192,107,52,39,187,51,12,52,90,77,91,162,203,174,79,131,235,2,93,167,156,160,13,197,143,37,194,72,48,66,115,30,131,235,254,70,115,178,59, +195,80,242,232,40,45,219,249,72,93,120,164,76,255,101,81,90,20,57,31,38,4,35,52,167,47,92,118,69,148,166,100,119,134,25,93,126,164,37,217,111,116,14,192,75,233,35,54,211,138,183,43,192,148,96,132,166,228,181,131,171,90,30,167,41,217,157,97,78,165,217, +140,223,151,3,202,193,123,231,207,137,50,78,39,110,134,89,193,8,77,217,91,30,46,10,172,161,41,217,157,97,218,45,39,24,151,216,130,142,208,68,195,87,114,25,143,213,141,96,94,48,66,83,198,194,69,55,209,148,236,206,136,67,195,175,104,94,209,180,22,208,72, +149,71,15,208,172,216,152,100,196,35,24,161,25,133,103,192,53,101,246,208,140,236,78,136,75,210,147,81,154,147,29,174,11,205,164,222,182,133,166,236,185,16,113,10,70,104,198,2,184,230,9,154,145,221,9,241,234,244,3,77,56,244,104,101,104,40,208,227,51, +26,155,87,5,113,11,70,104,198,165,112,73,237,92,154,144,221,9,241,171,248,54,141,68,254,154,6,93,181,91,78,89,238,157,176,34,24,161,9,159,195,37,15,211,132,236,78,176,228,198,227,148,28,125,32,5,58,187,100,61,5,27,154,195,154,96,132,198,98,65,184,99, +51,141,101,119,130,69,13,254,201,83,42,12,87,134,230,2,253,34,60,149,23,82,97,85,48,66,99,15,193,21,173,105,44,187,35,44,75,122,162,152,39,247,110,67,148,0,165,254,118,152,39,115,240,10,216,16,140,208,208,70,184,34,68,67,217,29,97,71,135,8,79,226,203, +243,81,66,84,120,58,151,127,176,228,52,216,18,140,208,80,43,184,32,113,31,141,156,232,8,123,42,188,201,223,219,213,7,37,72,237,127,20,243,55,50,239,11,192,166,96,132,70,30,131,11,154,209,200,137,142,176,237,146,175,248,107,7,30,44,133,146,165,241,139, +89,252,175,172,199,42,192,190,96,132,6,222,133,11,250,208,192,137,142,80,225,242,213,252,183,216,242,222,41,40,121,74,15,248,116,119,49,25,219,254,238,144,74,80,34,24,161,108,51,92,48,138,178,19,29,161,72,250,21,15,205,154,247,202,67,55,53,68,137,149, +88,235,172,178,80,39,24,161,168,40,5,206,155,75,209,137,14,240,57,38,24,161,232,76,56,111,39,37,39,58,192,231,160,96,132,146,222,112,94,148,130,19,29,224,115,84,211,40,5,55,195,121,49,10,70,192,231,176,57,20,220,12,231,21,243,212,10,42,193,231,176,215, +40,184,25,206,43,162,160,54,124,14,219,74,193,205,112,94,1,5,119,192,231,172,91,40,185,25,206,203,163,224,112,45,248,156,212,240,4,37,61,224,188,77,148,44,11,192,231,156,164,175,40,170,7,231,205,166,232,1,248,156,243,36,69,89,112,193,35,20,21,180,130, +207,41,29,163,20,173,132,11,174,162,108,83,26,124,206,168,16,161,236,101,184,160,17,13,188,12,159,51,222,162,129,91,224,130,132,61,52,208,29,62,39,244,163,129,252,74,112,195,179,52,112,176,6,124,234,5,143,209,192,59,112,69,11,26,89,8,159,114,137,95,208, +72,119,184,227,27,26,185,7,62,213,30,165,145,3,73,112,199,223,104,36,175,5,124,106,181,47,162,145,231,225,146,234,39,104,100,67,41,248,84,42,183,147,70,178,170,195,45,195,105,40,12,159,74,111,208,208,223,224,154,82,59,104,36,118,9,124,234,244,161,161, +77,73,112,79,79,26,218,87,21,62,85,234,28,165,161,139,224,166,37,52,52,15,62,69,18,62,165,161,247,224,170,51,114,104,104,16,124,106,140,160,161,125,213,224,174,59,104,40,167,9,124,42,180,41,164,145,216,37,112,219,92,26,90,151,2,159,125,101,182,209,80, +8,174,171,186,151,134,158,133,207,190,73,52,180,190,20,220,119,113,140,70,98,23,192,103,215,85,52,148,219,12,94,24,71,67,187,43,195,103,79,173,195,52,116,23,60,81,106,61,13,189,11,159,45,129,229,52,52,31,30,105,150,75,67,183,194,103,199,3,52,180,175, +42,188,114,55,13,157,104,8,159,117,173,10,104,36,118,49,188,179,128,134,190,78,130,207,170,180,77,52,244,60,60,84,125,63,13,61,9,159,85,175,208,208,55,41,240,210,101,52,20,237,8,159,53,221,105,40,183,41,188,245,2,13,253,80,1,62,43,106,28,164,161,65,240, +88,234,183,52,52,19,186,73,40,95,187,113,155,174,61,174,191,227,193,199,159,24,50,168,95,175,11,218,54,77,175,144,8,189,4,22,209,208,92,120,174,101,62,13,245,135,46,146,155,92,57,108,202,170,35,60,169,172,175,167,143,188,182,69,42,52,49,152,134,246,86, +133,247,238,165,161,99,245,225,185,132,214,3,158,157,191,181,136,134,162,187,22,134,6,157,151,12,175,181,200,163,145,88,55,104,32,176,152,134,190,72,132,151,2,45,6,207,61,202,184,100,47,26,210,38,1,30,42,181,129,134,198,66,11,167,29,164,161,199,224,153, +70,119,204,58,64,75,142,206,29,220,34,0,143,132,105,104,93,10,244,208,131,134,138,207,133,23,146,186,79,253,137,182,28,120,251,186,82,240,192,37,49,26,201,105,2,93,188,66,67,59,203,193,117,173,199,31,164,2,71,95,235,0,183,85,219,71,67,183,67,27,105,155, +104,104,42,220,149,62,108,35,149,217,249,248,233,112,213,68,26,122,31,26,105,85,64,67,93,225,158,178,55,46,143,82,173,47,238,168,4,215,156,94,68,35,123,170,64,39,15,208,208,23,112,75,157,23,178,233,128,252,201,141,224,146,105,52,18,187,16,90,9,44,163, +161,203,225,138,211,39,21,208,33,209,153,45,225,134,70,81,26,121,22,154,169,117,152,70,214,192,5,205,103,20,211,65,177,185,109,225,188,219,105,100,109,10,116,115,37,13,85,131,211,50,222,139,209,105,75,58,193,105,175,208,64,78,99,232,103,34,141,92,2,103, +157,187,136,174,88,113,17,156,245,5,13,220,6,13,149,222,74,3,35,224,164,26,211,232,154,121,65,56,233,56,101,239,65,75,173,11,41,155,5,231,36,220,125,148,46,202,29,153,2,231,28,166,104,119,101,232,105,24,101,111,193,49,231,172,161,203,182,94,4,199,108, +160,104,28,52,85,42,155,162,113,112,72,165,9,81,186,111,118,109,56,100,9,69,153,101,161,167,254,148,13,131,35,2,55,31,164,39,78,60,144,4,71,76,166,236,126,104,41,240,45,101,253,225,132,186,43,232,153,111,91,194,9,87,82,182,59,5,58,186,130,178,130,234, +112,64,207,35,244,80,238,64,56,32,113,55,101,3,160,163,21,148,189,13,245,146,159,167,199,166,151,133,122,143,81,182,53,1,250,57,151,6,186,64,185,224,87,244,220,230,150,80,174,86,33,101,215,64,63,115,41,219,8,229,174,60,74,13,228,14,132,114,47,80,182, +26,218,105,18,163,236,26,40,150,18,166,38,166,151,133,98,85,179,40,235,6,221,76,166,236,75,40,86,111,53,181,177,185,57,20,27,78,217,114,104,166,118,1,101,157,161,214,153,123,169,145,163,29,160,86,234,143,148,181,133,94,158,163,236,67,168,213,49,139,90, +201,235,9,181,110,162,236,61,104,165,226,113,138,162,45,161,212,149,121,212,76,241,0,40,149,176,158,162,104,99,232,100,4,101,83,161,212,192,98,218,115,244,171,133,179,94,15,63,57,236,238,155,250,223,57,116,84,232,31,111,127,184,234,48,109,122,8,74,93, +68,217,235,208,72,234,126,138,242,235,66,165,145,180,44,186,243,195,113,183,119,174,129,147,168,114,254,173,99,230,109,41,162,101,227,3,80,105,49,69,133,233,208,199,29,148,141,133,66,9,47,210,154,232,154,231,46,43,11,3,169,93,71,125,94,72,107,102,166, +64,161,51,163,20,141,131,54,18,182,83,148,85,25,234,36,191,77,11,98,27,198,247,170,8,147,202,92,50,230,235,98,90,176,180,12,20,154,66,81,118,101,232,226,58,202,134,67,157,192,91,140,223,150,145,117,17,167,234,247,174,101,252,150,166,64,157,58,133,20, +141,128,46,190,162,232,64,26,212,25,207,120,29,126,233,28,88,210,124,204,110,198,107,102,0,234,188,65,209,102,104,162,49,101,143,65,157,17,140,79,244,253,43,83,96,89,66,183,233,5,140,207,120,168,211,146,178,214,208,195,227,20,229,85,131,50,183,50,46, +133,147,207,128,77,181,195,57,140,203,67,80,103,17,69,97,232,97,27,69,19,161,76,207,98,198,33,239,165,122,80,160,218,232,99,140,199,0,40,115,33,69,251,19,161,131,54,20,197,154,66,149,14,185,52,239,196,179,167,65,145,138,143,30,161,121,197,61,161,204, +58,138,46,133,14,198,81,180,16,170,180,56,74,211,162,175,84,134,66,101,71,23,210,180,188,14,80,229,122,138,102,64,3,9,123,40,186,16,138,212,217,67,211,86,183,129,98,77,63,161,105,71,155,67,145,164,31,40,201,41,11,239,117,165,104,61,20,73,94,69,179,142, +222,149,0,245,110,216,79,179,54,151,133,34,127,163,168,63,188,55,137,162,155,160,200,88,154,53,173,58,28,81,225,197,40,77,154,14,69,202,101,81,178,4,158,75,201,164,100,111,10,212,232,17,163,57,123,47,128,99,218,108,167,73,3,161,200,51,148,20,215,132, +215,122,81,244,16,212,168,123,132,230,44,173,14,7,149,159,77,115,114,91,66,141,218,197,148,220,15,175,205,162,36,175,50,148,72,94,69,83,138,31,78,128,179,238,202,167,41,155,203,66,141,15,41,89,7,143,149,205,165,100,54,212,24,75,83,246,118,129,227,50, +118,208,148,233,80,227,58,138,154,193,91,253,40,234,14,37,122,196,104,198,178,234,112,65,249,119,104,202,64,40,81,42,147,146,167,225,173,133,148,28,72,130,10,117,143,208,140,9,9,112,199,19,52,35,183,37,148,120,133,146,31,2,240,82,181,34,74,194,80,226, +19,154,241,119,184,230,206,40,77,248,54,9,42,156,67,81,103,120,233,46,138,50,160,194,13,52,33,122,39,92,116,77,62,77,120,0,74,108,162,100,18,188,244,57,37,223,65,133,10,251,104,44,255,90,184,170,115,22,141,157,168,13,21,134,81,146,191,44,60,240,220,242, +240,64,213,206,119,189,18,163,100,40,84,120,129,198,142,117,133,203,206,220,75,99,179,161,66,173,98,26,250,113,209,115,55,183,41,3,151,84,238,56,232,197,143,15,208,72,180,22,20,104,85,76,67,199,219,192,117,245,247,210,216,69,80,97,49,205,137,237,154, +63,250,134,86,169,112,80,197,243,111,31,191,124,31,205,89,10,5,2,171,104,168,224,66,120,224,204,44,26,218,154,2,5,250,50,30,197,91,231,60,209,167,121,50,20,43,127,238,192,208,210,61,140,71,63,40,48,128,134,162,189,225,137,206,249,52,52,18,10,164,102, +49,110,133,27,103,61,122,117,227,68,40,80,174,221,173,207,47,254,137,113,59,81,26,246,85,62,68,67,127,133,71,174,137,210,72,110,16,10,188,69,139,242,215,191,57,162,231,233,9,176,168,76,219,155,159,91,248,67,140,214,188,11,5,94,163,161,81,240,204,157, +52,52,15,10,92,79,91,114,86,135,123,148,71,156,90,222,63,239,251,24,237,24,0,251,206,138,209,200,68,120,232,9,26,186,8,246,85,42,166,93,197,95,62,221,14,102,85,190,121,198,126,218,86,11,246,205,166,145,207,18,225,165,119,104,100,5,20,88,65,21,86,118, +15,192,132,250,47,230,80,129,245,176,175,73,148,6,14,214,130,167,202,239,160,145,78,176,111,40,213,248,238,166,100,24,104,51,171,152,74,140,134,125,83,105,32,118,9,60,150,145,79,3,75,96,95,51,170,178,185,53,36,149,103,81,149,78,176,173,126,17,13,140, +134,231,238,162,145,182,176,111,23,85,41,124,40,1,167,212,109,55,85,201,74,130,109,19,104,224,243,36,120,111,54,13,204,133,125,47,80,157,149,245,113,114,169,161,24,149,121,7,182,213,202,167,236,112,58,52,80,126,59,101,177,150,176,237,98,42,116,172,3, +78,166,218,55,84,232,86,216,22,162,129,171,160,133,54,81,202,102,194,182,148,19,84,232,68,7,252,81,245,239,168,82,45,216,85,45,135,178,15,160,137,23,41,139,54,130,109,115,168,210,137,14,248,189,26,27,169,210,122,216,246,52,101,185,245,161,137,10,251, +41,155,12,219,110,162,82,39,58,224,183,78,219,68,165,158,132,93,201,135,41,27,9,109,220,64,89,126,37,216,85,250,40,149,58,90,7,191,150,188,134,74,69,235,195,174,94,148,109,77,129,62,62,161,236,14,216,22,166,90,31,39,224,87,158,161,90,31,192,182,247,40, +235,6,141,52,45,164,232,11,216,214,132,138,13,193,255,116,137,82,173,75,96,87,165,2,138,102,66,43,163,41,59,29,182,189,67,181,10,206,194,127,84,250,145,106,173,9,192,174,65,20,21,214,131,86,202,30,161,232,113,216,86,110,19,213,218,144,128,127,155,78, +181,246,215,129,109,171,40,154,12,205,60,74,209,78,216,215,48,147,106,93,141,95,52,142,82,169,130,243,96,91,67,138,162,141,160,153,138,199,41,234,0,251,186,101,81,169,175,240,139,215,169,84,97,63,216,247,119,138,102,66,59,163,41,122,13,10,164,47,166, +82,93,241,179,244,66,170,244,221,217,176,47,176,139,146,88,75,104,167,90,14,37,71,75,65,133,129,153,84,104,49,126,22,162,66,209,177,165,160,64,71,138,230,66,67,97,138,174,131,18,41,151,190,182,159,202,52,6,80,46,155,170,20,127,58,184,14,148,8,83,212, +22,26,170,93,64,201,219,80,37,225,204,235,159,154,187,61,74,5,238,5,208,131,42,20,109,126,247,239,189,171,65,149,13,148,172,132,150,166,83,114,32,0,165,210,50,250,63,179,224,251,24,109,153,15,224,69,218,83,188,109,206,168,190,45,83,160,82,181,24,37,3, +161,165,110,20,181,128,3,202,182,189,101,236,162,159,104,213,241,36,96,43,173,138,238,152,247,244,13,173,82,161,94,111,74,242,42,64,75,9,187,41,25,12,199,148,63,119,96,120,217,94,90,112,46,234,209,130,216,174,15,158,233,159,145,6,167,76,160,100,22,52, +53,134,146,185,112,88,229,142,131,94,252,248,32,227,50,18,183,49,46,177,200,135,207,222,212,166,12,156,181,141,146,43,160,169,230,148,28,77,128,27,170,117,185,251,213,21,71,104,210,100,140,163,89,63,46,26,123,203,57,101,225,130,116,74,14,36,65,87,107, +41,105,3,247,156,214,237,222,137,171,178,104,104,30,102,208,216,238,37,227,6,180,47,15,215,244,167,36,4,109,221,75,201,16,184,45,253,146,7,38,239,165,228,11,44,163,36,250,113,248,182,243,42,194,101,83,40,201,128,182,170,23,83,176,8,94,40,243,44,5,91, +240,47,10,86,183,130,23,126,160,96,63,52,246,53,5,217,201,240,66,226,62,158,218,97,236,167,160,11,188,208,128,146,153,208,216,24,74,206,131,39,38,241,212,162,40,230,169,29,78,128,23,122,81,50,16,26,187,132,146,59,224,137,48,5,160,32,2,79,12,163,164,1, +52,86,166,144,130,16,60,17,166,0,20,68,224,137,201,20,124,15,173,125,78,193,66,120,34,76,1,40,136,192,19,171,40,120,29,90,27,69,193,46,120,34,76,1,40,136,192,19,71,40,184,30,90,235,74,65,52,21,94,8,83,0,10,34,240,66,85,74,106,67,107,169,69,20,180,128, +23,194,20,128,130,8,188,208,129,130,99,208,220,22,10,174,133,23,194,20,128,130,8,188,48,128,130,175,161,185,185,20,140,132,23,194,20,128,130,8,188,240,28,5,51,160,185,49,20,76,135,23,194,20,128,130,8,188,48,159,130,71,160,185,91,40,248,26,94,8,83,0,10, +34,240,194,22,10,250,64,115,231,81,144,5,47,132,41,0,5,17,120,225,32,5,173,160,185,202,148,36,194,3,97,10,64,65,4,94,200,227,169,197,202,64,119,135,40,168,0,15,132,41,0,5,17,120,32,137,130,61,208,222,23,20,164,195,3,97,10,64,65,4,30,168,68,193,183,208, +222,2,10,154,194,3,97,10,64,65,4,30,168,67,193,42,104,239,109,10,218,194,3,97,10,64,65,4,30,104,70,193,98,104,111,18,5,23,192,3,97,10,64,65,4,30,104,71,193,59,208,94,136,130,94,240,64,152,2,80,16,129,7,186,81,48,25,218,123,130,130,126,240,64,152,2,80, +16,129,7,174,164,32,12,237,13,165,96,16,60,16,166,0,20,68,224,129,254,20,140,130,246,238,164,96,8,60,16,166,0,20,68,224,129,187,40,24,2,237,245,167,224,9,120,32,76,1,40,136,192,3,131,40,24,6,237,221,68,193,227,240,64,152,2,80,16,129,7,250,81,240,36,180, +119,55,5,15,194,3,97,10,64,65,4,30,232,69,193,11,208,222,48,10,238,128,7,194,20,128,130,8,60,112,1,5,83,160,189,39,41,184,30,30,8,83,0,10,34,240,64,91,10,222,131,246,194,20,244,128,7,194,20,128,130,8,60,208,132,130,165,208,222,235,20,116,129,7,194,20, +128,130,8,60,144,78,193,151,208,222,44,10,218,192,3,97,10,64,65,4,30,168,64,193,70,104,111,33,5,141,225,129,48,5,160,32,2,15,36,82,112,0,218,251,138,130,90,240,64,152,2,80,16,129,23,114,40,168,0,221,29,165,160,28,60,16,166,0,20,68,224,133,3,20,180,133, +230,106,80,16,75,128,7,194,20,128,130,8,188,240,29,5,253,160,185,206,20,28,134,23,194,20,128,130,8,188,240,30,5,79,64,115,183,83,240,5,188,16,166,0,20,68,224,133,167,41,152,5,205,141,163,96,50,188,16,166,0,20,68,224,133,27,41,248,6,154,251,144,130,161, +240,66,152,2,80,16,129,23,218,81,144,19,128,222,118,82,208,11,94,8,83,0,10,34,240,66,69,74,26,64,107,101,163,20,52,134,23,194,20,128,130,8,60,177,159,130,91,161,181,203,40,40,74,134,23,194,20,128,130,8,60,241,25,5,111,66,107,207,81,176,21,158,8,83,0, +10,34,240,196,107,20,236,131,214,214,80,48,15,158,8,83,0,10,34,240,196,253,148,52,131,198,42,70,41,120,22,158,8,83,0,10,34,240,196,21,148,220,3,141,245,162,100,0,60,17,166,0,20,68,224,137,218,148,188,15,141,141,167,164,53,60,49,147,167,22,69,140,167, +182,15,222,216,74,193,209,4,232,107,3,5,71,19,224,133,114,185,60,181,3,56,68,65,27,120,98,2,37,29,161,173,186,49,10,230,194,11,149,95,167,96,3,54,82,176,168,6,188,208,155,146,73,208,214,72,74,6,195,101,9,167,247,28,49,227,40,37,203,241,49,37,199,95,25, +212,161,18,220,86,45,70,65,86,42,116,181,133,146,22,112,77,194,233,61,134,79,95,151,75,67,111,226,109,26,218,179,116,220,128,118,229,224,162,13,148,244,134,166,206,161,228,64,0,46,72,104,208,99,248,180,181,185,52,41,132,241,52,39,22,249,112,204,141,25, +105,112,197,120,74,22,64,83,47,81,50,11,206,10,52,232,62,108,218,218,28,198,229,78,12,102,60,162,219,231,62,249,151,150,41,112,88,47,74,138,170,67,75,41,135,41,185,3,78,9,212,239,62,108,234,154,28,90,208,16,205,24,191,162,77,239,60,118,109,147,36,56, +166,98,148,146,251,160,165,43,41,106,4,245,2,245,175,24,58,117,77,14,173,218,5,96,55,45,42,248,215,91,35,123,53,76,128,19,214,80,242,13,180,244,62,37,63,65,169,64,240,138,33,111,172,206,166,61,19,0,76,166,45,185,107,167,14,189,188,94,0,106,141,161,168, +27,52,116,70,148,146,169,80,165,194,229,67,222,248,58,155,42,92,13,160,47,21,56,254,229,63,254,118,81,45,40,211,134,162,79,160,161,41,20,117,135,18,213,111,91,84,72,85,242,42,0,168,90,68,85,246,79,188,56,25,106,108,162,232,124,104,39,88,68,201,193,36, +40,80,106,108,148,10,189,140,159,77,165,66,153,161,210,80,97,4,69,11,161,157,87,40,26,15,5,206,218,64,149,138,234,225,103,77,99,84,105,91,59,40,80,39,74,81,6,52,83,43,159,162,214,176,175,127,1,149,122,3,191,152,67,165,138,31,133,2,31,81,244,30,52,243, +60,69,27,97,95,135,2,42,21,109,130,95,180,165,98,247,195,190,155,40,138,53,135,86,170,101,83,52,12,182,213,61,64,181,222,196,127,44,164,90,197,151,194,182,178,57,20,45,133,86,38,82,20,77,135,93,9,235,168,214,222,42,248,143,58,71,169,86,214,25,176,109, +6,101,189,161,145,118,49,138,150,195,182,238,84,43,118,49,254,167,15,21,123,27,182,93,76,217,238,178,208,70,226,58,202,110,132,109,139,168,86,24,191,54,141,106,21,165,195,174,196,61,148,141,133,54,254,74,89,118,89,216,213,48,70,165,190,75,197,175,149, +255,158,106,141,134,109,15,81,86,212,2,154,168,145,69,217,11,176,109,52,149,250,190,30,126,171,197,65,42,117,164,20,236,42,159,69,217,10,104,98,58,101,5,117,96,219,119,84,105,87,93,252,94,243,3,84,234,82,216,54,138,6,110,129,22,46,160,129,73,176,45,72, +149,118,214,193,31,53,219,79,149,94,130,109,85,178,41,59,209,24,26,168,190,151,178,226,211,97,219,221,84,104,91,58,78,166,233,62,42,20,129,125,99,105,224,95,169,240,92,194,82,26,152,1,251,22,81,157,41,229,112,114,167,45,160,66,45,96,91,205,124,26,120, +13,158,123,152,6,98,205,97,91,233,60,170,114,248,26,156,218,29,217,84,102,4,236,123,153,70,250,194,99,93,138,105,224,61,216,215,147,170,44,169,9,73,195,127,82,149,47,96,95,189,66,26,56,222,16,158,170,190,151,70,50,96,223,107,84,99,249,69,48,144,112,221, +26,170,17,173,10,251,166,208,200,186,84,120,40,97,25,141,44,130,2,187,169,64,241,172,214,48,227,130,37,84,162,63,236,107,84,68,35,115,18,225,157,9,52,116,46,236,107,69,219,114,151,14,107,0,179,90,141,254,58,74,219,102,65,129,103,105,104,34,60,243,119, +26,154,6,5,30,166,45,153,159,141,234,82,10,241,169,120,229,139,27,10,105,75,86,50,236,43,243,19,13,61,5,143,220,73,67,71,107,64,129,127,210,162,35,43,39,12,190,176,38,44,74,110,222,103,212,156,109,81,90,117,1,20,184,134,198,238,133,39,174,141,210,208, +221,80,160,110,140,113,59,188,226,213,123,46,56,13,10,164,101,244,31,243,225,15,180,224,69,168,176,136,134,98,215,195,3,93,243,105,104,77,2,20,120,152,241,56,244,217,43,127,237,90,3,138,149,107,63,48,188,124,31,227,114,36,5,10,52,204,167,161,194,43,224, +186,54,199,104,40,122,14,84,216,78,115,14,126,250,242,221,93,170,195,65,85,58,223,253,202,138,76,154,117,29,84,120,156,198,10,175,135,203,46,60,78,99,19,160,194,249,52,116,240,147,151,239,234,92,13,46,169,117,241,223,94,255,234,4,141,45,130,10,169,59, +104,44,118,47,92,213,187,128,198,14,86,130,10,147,40,249,225,165,59,59,87,133,251,2,193,238,195,103,124,147,79,73,52,29,42,92,74,51,158,130,139,254,26,165,9,55,67,133,180,99,148,220,4,47,85,41,160,100,36,148,120,135,102,76,76,132,91,70,209,140,21,1,168, +112,61,37,57,229,224,169,247,40,217,14,37,42,255,64,51,230,164,194,21,137,19,105,198,145,186,80,98,41,37,111,193,91,189,40,234,4,37,206,45,164,25,235,26,194,5,181,62,163,25,177,30,80,34,61,74,201,229,240,86,242,33,74,222,128,26,15,210,148,227,125,225, +184,75,14,210,148,177,80,99,4,37,7,146,224,177,23,41,201,46,7,37,2,243,105,206,107,169,112,84,210,232,24,77,89,149,12,53,182,80,18,134,215,218,82,52,0,106,84,254,129,230,252,171,49,28,148,254,57,205,57,82,23,106,116,160,168,13,60,183,153,146,85,80,228, +220,66,154,115,226,22,56,230,170,195,52,39,214,3,138,204,165,100,51,188,55,130,162,246,80,228,65,154,245,89,115,56,162,254,7,52,107,44,20,105,28,163,100,36,188,87,39,74,201,251,80,36,48,159,102,21,62,91,6,202,165,140,204,165,89,171,146,161,200,68,74, +98,245,160,129,143,40,137,53,129,34,149,54,210,180,31,175,134,98,221,182,210,180,31,211,161,72,141,124,74,86,64,7,55,81,244,58,84,73,255,137,230,45,108,2,133,234,205,164,121,71,154,65,149,39,41,186,13,58,40,155,77,73,65,45,168,210,236,8,205,139,206,110, +5,69,26,77,46,164,121,185,231,65,149,50,153,148,228,87,132,22,166,81,244,28,148,57,47,151,241,88,112,46,20,104,57,51,202,56,20,117,135,50,247,82,244,46,244,208,141,162,227,21,161,76,143,98,198,229,227,11,97,83,219,185,49,198,229,22,40,147,20,161,168, +23,244,144,176,155,162,17,80,231,86,198,233,155,251,170,195,178,10,3,87,50,78,35,160,206,95,40,58,146,2,77,60,67,209,254,82,80,103,4,227,85,180,160,119,42,44,72,186,98,86,30,227,53,30,10,173,163,232,21,232,162,25,101,119,64,161,23,24,191,172,73,29,19, +16,159,140,208,1,198,239,237,0,212,185,152,178,182,208,198,106,138,182,39,66,157,192,11,180,226,232,251,247,52,131,73,13,6,206,220,79,43,222,74,134,58,129,117,20,125,10,125,244,165,236,118,168,52,146,22,237,123,243,214,6,1,200,106,95,255,250,247,180, +104,124,0,10,221,64,217,37,208,71,226,54,138,246,149,129,74,3,139,105,89,206,55,179,158,232,215,182,2,254,160,236,217,125,30,157,177,250,24,173,27,1,149,74,125,79,209,58,232,100,0,101,143,67,169,94,121,180,233,192,198,47,151,190,55,229,133,39,135,13, +25,21,158,252,206,146,85,223,237,165,77,197,183,66,169,251,41,235,3,157,164,252,68,81,118,77,40,213,241,40,53,147,219,19,74,85,60,66,209,246,68,104,101,48,101,19,161,86,203,61,212,202,209,14,80,107,12,101,183,67,47,165,15,82,84,220,28,106,5,183,82,35, +123,90,64,173,58,121,20,237,45,5,205,60,68,217,135,80,172,234,34,106,99,85,29,40,246,6,101,67,161,155,10,89,148,93,0,197,2,195,139,168,133,216,216,100,40,118,102,148,162,163,229,160,157,167,40,91,27,128,106,29,126,162,6,142,244,128,114,139,41,123,10, +250,169,150,67,89,63,40,87,229,67,122,110,85,93,40,215,158,178,220,234,208,80,152,178,239,19,161,92,96,72,17,61,21,27,155,12,245,166,81,246,18,116,148,94,64,89,79,56,224,220,31,233,161,35,61,224,128,42,121,20,21,5,161,165,73,148,45,130,19,42,191,67,207, +124,82,23,78,120,144,178,25,208,83,195,98,138,98,13,224,136,75,119,208,19,251,110,128,51,150,81,20,107,1,77,205,164,236,1,56,35,245,241,124,186,174,248,133,10,112,200,119,20,125,0,93,181,140,81,20,130,83,26,46,162,203,86,181,130,99,50,41,186,22,218,90, +66,209,44,56,231,154,159,232,162,67,3,2,112,76,42,101,235,82,160,169,6,199,41,90,1,7,149,121,182,136,46,137,189,86,25,14,74,139,82,246,28,244,148,244,79,202,214,192,81,141,166,20,210,5,209,217,103,193,89,91,41,139,93,8,45,61,73,3,51,224,176,122,47,231, +211,97,69,83,155,192,105,239,208,192,158,42,208,80,167,40,13,12,131,227,106,142,205,166,131,242,39,212,135,243,30,161,145,57,208,79,165,31,105,228,114,184,160,202,168,44,58,36,39,84,11,110,200,160,161,129,208,206,59,52,82,80,29,174,40,255,208,30,58,224, +240,211,213,224,146,121,52,146,125,6,52,51,128,134,94,134,91,18,47,158,145,67,165,10,222,235,149,12,215,180,138,209,200,154,100,104,165,113,54,141,228,215,134,139,202,222,244,81,148,170,172,26,84,9,174,122,151,134,70,67,39,41,107,105,104,60,92,86,103, +196,38,42,176,235,239,13,225,182,58,153,52,18,237,2,141,60,71,67,251,171,193,125,109,198,172,137,210,134,216,134,112,199,0,60,208,155,134,126,170,4,109,92,20,163,161,203,224,141,138,189,198,111,136,209,138,109,19,122,87,131,87,222,160,161,217,208,69, +213,189,52,52,30,30,170,214,123,194,86,198,229,135,41,253,211,225,165,114,59,105,232,22,104,98,62,13,125,155,10,143,213,190,226,254,137,159,29,160,161,35,171,38,15,187,178,1,60,215,190,136,70,78,156,14,45,220,77,67,121,45,160,135,138,237,111,26,61,103, +227,129,92,254,65,222,193,45,243,159,27,208,161,42,116,241,40,13,125,149,4,13,180,200,163,161,193,208,76,98,133,244,166,109,47,232,213,111,208,93,253,175,236,214,174,89,157,74,73,208,77,226,23,52,244,36,188,151,250,45,13,45,12,192,23,183,250,199,104, +36,218,17,158,123,145,134,14,212,128,207,130,254,52,20,169,0,143,117,167,177,43,224,179,100,38,13,189,5,111,157,118,144,134,94,130,207,154,138,63,208,80,127,120,41,176,132,134,190,75,133,207,162,78,81,26,57,86,31,30,122,128,134,242,207,132,207,178,167, +104,104,85,34,60,115,118,1,13,221,7,159,117,201,95,211,208,227,240,74,233,45,52,180,56,0,159,13,141,178,105,164,248,60,120,100,18,13,29,58,13,62,91,6,210,208,174,242,240,196,53,52,214,3,62,155,230,208,208,116,120,33,61,147,134,94,129,207,174,42,123,104, +232,47,112,95,194,167,52,180,41,13,62,219,186,197,104,36,171,30,92,247,16,13,21,180,130,79,129,177,52,180,50,17,46,107,87,68,67,15,192,167,66,202,122,26,26,2,119,37,111,166,161,101,1,248,148,104,150,75,35,39,106,193,85,67,104,232,112,77,248,20,185,155, +134,166,195,77,53,143,211,80,47,248,148,89,64,35,177,243,224,162,25,52,244,26,124,234,84,63,64,35,107,19,224,154,14,52,180,165,52,124,10,93,78,67,215,193,53,11,105,164,32,3,62,165,94,162,145,5,112,75,141,98,26,25,2,159,90,169,27,105,160,168,26,92,114, +31,141,124,20,128,79,177,179,242,105,96,48,92,178,150,6,142,212,134,79,185,251,105,96,53,220,209,140,70,174,134,79,189,192,50,26,104,0,87,140,160,129,73,240,57,161,214,97,202,174,131,43,102,81,182,181,12,124,142,184,138,178,81,112,197,102,138,10,91,195, +231,144,73,20,205,131,27,82,139,41,26,6,159,83,202,108,165,228,123,184,33,131,162,79,18,224,115,76,155,66,74,202,195,5,55,82,146,153,14,159,131,70,80,18,132,11,238,164,228,90,248,156,148,144,73,65,16,46,184,139,130,181,240,57,107,46,5,65,184,224,175, +20,140,129,207,89,171,41,8,194,5,247,80,48,3,62,71,93,76,73,16,46,184,151,130,226,51,224,115,80,70,38,37,213,225,130,254,148,68,130,240,57,38,35,147,146,35,112,195,217,20,69,130,240,253,87,114,89,40,148,145,73,209,10,184,33,181,152,162,72,16,234,84,62, +183,79,231,122,137,40,137,202,14,90,248,175,131,49,70,230,63,117,1,212,200,200,164,236,85,184,98,51,101,145,32,148,72,30,248,249,33,254,172,232,171,1,101,80,194,156,249,234,113,254,215,138,78,80,32,35,147,6,254,10,87,188,67,3,145,32,236,75,30,184,139, +255,115,236,165,58,40,65,26,206,230,111,45,109,12,187,50,50,105,164,51,92,49,140,70,34,65,216,117,193,46,254,86,254,184,170,40,33,170,189,80,200,223,203,185,29,246,100,100,210,200,193,36,184,162,1,13,69,130,176,37,229,217,24,255,224,248,163,101,81,2, +164,61,116,140,39,243,126,21,216,144,145,73,67,47,194,37,171,104,40,18,132,13,77,214,241,164,14,12,78,129,230,18,110,221,205,83,216,123,17,44,203,200,164,177,115,224,146,187,104,44,18,132,101,131,114,120,42,223,223,152,0,157,93,254,45,79,45,246,124,10, +172,201,200,164,177,173,112,75,213,66,26,139,4,97,77,213,121,148,124,219,19,218,106,247,49,101,235,155,193,138,140,76,154,240,8,92,243,62,77,136,4,97,197,37,251,104,224,235,222,137,208,80,224,242,79,104,40,247,46,196,47,35,147,38,100,86,134,107,154,23, +211,132,72,16,113,43,21,142,209,216,247,247,149,133,102,82,110,254,142,166,124,80,13,113,202,200,164,25,131,225,162,151,104,70,36,136,56,181,216,64,115,142,142,169,13,141,84,24,186,135,102,237,191,20,113,201,200,164,25,155,147,224,162,42,153,52,35,18, +68,92,238,201,163,105,133,211,206,130,38,210,159,59,198,56,196,198,167,194,188,140,76,154,114,57,92,53,152,166,68,130,48,175,198,66,198,103,217,165,208,192,89,83,11,25,167,13,45,96,86,70,38,77,249,16,238,74,90,75,83,34,65,152,213,253,32,227,182,253,225, +186,240,84,213,123,214,210,130,188,193,1,152,146,145,73,83,118,85,133,203,210,247,210,148,72,16,166,164,189,76,75,98,31,245,47,13,143,36,247,156,83,72,139,22,214,128,9,25,153,52,229,120,115,184,238,156,60,154,18,9,194,132,86,155,104,217,241,201,157,2, +112,223,89,161,131,180,225,96,119,24,202,200,164,41,209,238,240,64,95,154,19,9,194,72,224,129,2,218,178,243,177,250,112,85,181,251,214,211,174,151,211,32,203,200,164,57,67,224,137,191,211,156,72,16,178,90,203,104,91,236,139,17,103,194,37,77,30,248,184, +136,10,108,60,11,146,140,76,154,19,130,71,66,52,39,18,132,228,170,195,84,227,199,9,221,75,195,97,165,46,30,191,131,170,228,223,31,192,41,101,100,210,156,16,60,19,162,57,145,32,78,169,204,36,42,148,183,240,238,32,28,83,107,224,251,39,168,212,210,154,56, +133,140,76,154,19,130,135,66,52,39,18,196,41,180,217,74,213,190,27,221,16,14,72,127,116,109,140,202,29,234,133,147,202,200,164,57,33,120,42,68,115,34,65,156,76,194,240,66,58,32,182,168,123,2,212,234,250,110,17,157,49,161,52,254,40,35,147,230,132,224, +177,16,205,137,4,241,71,117,62,165,83,214,213,133,66,167,173,164,115,182,100,224,247,50,50,105,78,8,158,11,209,156,72,16,191,215,251,40,157,115,160,3,148,105,179,155,78,42,24,26,192,111,100,100,210,156,16,52,16,162,57,145,32,126,163,220,27,116,84,65, +127,40,210,59,143,14,251,168,54,126,37,35,147,230,132,160,133,16,205,137,4,241,43,237,119,210,97,5,103,65,137,38,121,116,220,145,107,240,95,25,153,52,39,4,77,132,104,78,36,136,255,72,124,180,136,142,219,80,10,10,36,126,73,55,252,163,12,126,145,145,73, +115,66,208,70,136,230,68,130,248,69,240,115,186,225,57,40,48,130,238,216,214,22,63,203,200,164,57,33,104,36,68,115,34,65,252,172,223,49,186,34,90,29,182,149,206,161,75,10,71,36,0,231,103,210,156,16,180,18,162,57,145,230,64,165,183,232,150,219,96,219, +85,116,207,158,87,223,142,210,156,16,52,19,162,57,133,111,205,206,165,107,22,193,182,105,212,81,8,218,9,209,33,63,209,186,194,10,176,41,41,147,214,125,117,227,74,58,34,4,13,133,232,132,172,191,224,178,79,104,217,229,176,41,131,150,45,233,10,36,62,82, +68,245,66,208,82,136,234,173,172,135,255,239,156,119,163,180,102,8,108,186,145,214,20,207,58,27,255,167,253,78,170,22,130,166,66,84,172,232,225,68,252,162,209,196,124,90,241,6,108,26,67,43,242,39,52,196,127,148,155,70,181,66,208,86,136,74,237,104,135, +255,57,109,116,22,227,247,53,108,90,192,248,29,123,230,52,252,90,223,44,42,20,130,198,66,84,104,74,89,252,70,185,7,119,51,94,217,1,216,19,97,188,246,13,175,128,223,169,183,146,202,132,160,181,16,85,201,188,14,127,144,114,203,38,198,41,8,91,202,198,24, +159,29,119,164,226,143,18,31,41,162,26,33,104,46,68,53,62,73,199,201,4,122,126,193,184,92,1,91,206,97,92,214,245,73,196,201,181,223,73,21,66,208,94,136,10,20,14,75,192,169,116,152,145,77,243,134,192,150,91,104,222,241,55,186,226,212,202,77,165,125,33, +148,0,33,218,182,181,53,36,101,250,45,41,166,73,111,192,150,231,105,82,209,194,191,148,134,172,111,22,109,10,161,68,8,209,166,137,101,96,164,230,253,235,104,202,106,216,178,152,166,172,185,183,6,140,213,91,73,91,66,40,33,66,180,227,240,149,48,165,249, +232,31,105,44,59,0,59,126,162,177,200,83,77,97,78,226,35,69,180,46,132,18,35,68,235,150,213,130,89,129,46,175,103,209,72,125,216,80,129,70,178,38,117,14,192,188,246,59,105,85,8,37,72,136,22,21,60,16,64,60,82,175,155,95,72,209,21,176,225,60,138,10,231, +93,151,138,248,148,155,74,107,66,40,81,66,180,100,83,43,196,173,234,221,153,20,12,133,13,183,81,144,121,119,21,88,208,55,139,22,132,80,194,132,104,193,203,105,176,226,3,10,166,194,134,241,20,124,0,107,234,173,96,220,66,40,113,66,140,215,193,238,176,102, +12,5,107,96,195,114,10,70,195,162,196,135,139,24,159,16,74,160,16,227,179,168,6,44,186,145,130,156,0,172,219,71,65,63,88,214,110,39,227,17,66,137,244,60,227,144,55,56,0,171,90,83,82,31,150,85,166,228,108,88,87,110,42,77,139,62,136,18,106,80,33,205,250, +182,37,172,43,29,163,160,59,44,235,68,65,52,21,118,244,205,162,57,89,151,161,196,234,124,136,166,196,198,167,194,142,93,20,12,131,101,119,82,176,13,246,212,93,65,51,182,54,70,9,22,220,64,19,246,95,10,123,62,160,96,42,44,123,137,130,57,176,41,113,104, +14,13,45,174,136,18,173,236,91,52,18,155,82,21,54,61,67,193,26,88,246,41,5,163,96,91,189,121,148,109,239,19,64,73,119,222,74,138,190,237,8,219,110,164,32,39,0,171,14,81,208,23,10,244,140,240,212,246,223,149,140,63,131,238,223,242,148,14,62,152,4,251, +90,83,210,0,22,85,167,164,5,84,72,190,246,163,24,79,234,200,35,101,240,39,145,112,211,170,40,79,230,211,190,41,80,161,116,140,130,238,176,168,43,5,69,41,80,228,140,231,127,224,239,237,10,119,77,194,159,73,141,1,243,115,249,27,5,171,158,110,10,85,118, +82,48,12,22,221,67,193,70,40,148,222,231,133,53,71,98,252,89,225,79,171,231,143,108,137,63,161,210,61,135,143,159,189,98,251,137,220,31,191,89,54,243,225,206,105,80,232,3,10,166,193,162,9,20,204,134,106,9,85,155,156,219,162,106,0,190,248,61,67,193,90, +88,180,146,130,199,224,211,71,127,10,114,18,96,77,38,5,215,192,167,143,12,74,26,192,146,90,148,52,129,79,31,165,163,20,244,128,37,23,81,144,159,8,159,70,118,82,48,28,150,220,71,193,191,224,211,201,124,10,166,193,146,127,80,240,22,124,58,25,77,193,90, +88,242,79,10,30,130,79,39,253,41,200,77,128,21,199,40,232,5,159,78,50,40,57,29,22,212,165,228,116,248,116,146,22,165,160,7,44,184,140,130,220,4,248,180,178,131,130,225,176,224,65,10,214,192,167,151,249,20,76,135,5,83,40,152,10,159,94,70,83,176,14,22, +172,166,96,40,124,122,233,71,65,110,2,226,22,200,166,224,114,248,244,114,54,37,167,35,110,245,41,169,7,159,94,210,162,20,244,68,220,122,80,112,60,0,159,102,118,80,48,2,113,27,78,193,151,240,233,102,30,5,51,16,183,233,20,188,14,159,110,158,166,224,104, +101,196,169,242,81,10,254,6,159,110,250,81,242,122,89,196,165,220,235,148,92,12,159,110,206,166,40,103,254,219,113,248,32,151,162,90,240,233,38,45,74,215,28,133,79,63,219,232,154,21,240,233,103,18,93,51,10,62,253,244,165,107,186,192,167,159,234,49,186, +36,183,20,124,26,218,64,151,44,133,79,71,33,186,100,24,124,58,106,71,119,20,55,128,79,75,159,209,21,179,224,211,211,229,116,69,107,248,244,20,248,150,46,88,14,159,174,250,211,5,23,193,167,171,164,181,116,220,18,248,244,213,52,143,14,59,92,19,62,141,221, +75,135,93,3,159,206,2,203,233,168,41,240,233,45,253,32,29,180,173,28,124,154,107,121,136,142,217,153,14,159,246,206,58,76,135,236,170,3,95,9,208,234,8,29,241,125,93,248,74,132,179,127,164,3,190,171,7,95,9,81,113,38,85,139,133,83,225,43,57,110,200,162, +82,123,47,134,175,68,169,183,136,234,68,223,172,2,95,73,211,246,253,24,149,40,122,163,9,124,37,81,243,25,197,180,45,239,229,122,240,149,84,213,111,152,186,151,54,236,154,112,117,5,248,74,182,22,247,189,240,246,39,27,15,199,24,135,232,129,13,203,223,12, +221,217,16,127,122,255,15,174,60,73,225,178,56,111,16,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; + +const char* settings_png = (const char*) temp_binary_data_9; + + +const char* getNamedResource (const char* resourceNameUTF8, int& numBytes) +{ + unsigned int hash = 0; + if (resourceNameUTF8 != 0) + while (*resourceNameUTF8 != 0) + hash = 31 * hash + (unsigned int) *resourceNameUTF8++; + + switch (hash) + { + case 0x9fa71e2e: numBytes = 479; return CreditsAU; + case 0x553cd12e: numBytes = 624; return CreditsLV2; + case 0x553cf67d: numBytes = 537; return CreditsVST; + case 0xcacab454: numBytes = 340712; return DejaVuSansMono_ttf; + case 0xe1dcce5f: numBytes = 4098; return copy_png; + case 0x4e66dfa3: numBytes = 3299; return flower_center_png; + case 0x44524977: numBytes = 22287; return flower_petals_png; + case 0x0340271f: numBytes = 5113; return garbage_png; + case 0xb5baee83: numBytes = 8380; return reload_png; + case 0x1fded40d: numBytes = 12539; return settings_png; + default: break; + } + + numBytes = 0; + return nullptr; +} + +const char* namedResourceList[] = +{ + "CreditsAU", + "CreditsLV2", + "CreditsVST", + "DejaVuSansMono_ttf", + "copy_png", + "flower_center_png", + "flower_petals_png", + "garbage_png", + "reload_png", + "settings_png" +}; + +const char* originalFilenames[] = +{ + "CreditsAU", + "CreditsLV2", + "CreditsVST", + "DejaVuSansMono.ttf", + "copy.png", + "flower_center.png", + "flower_petals.png", + "garbage.png", + "reload.png", + "settings.png" +}; + +const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8) +{ + for (unsigned int i = 0; i < (sizeof (namedResourceList) / sizeof (namedResourceList[0])); ++i) + { + if (namedResourceList[i] == resourceNameUTF8) + return originalFilenames[i]; + } + + return nullptr; +} + +} diff --git a/ports/camomile/source/BinaryData.h b/ports/camomile/source/BinaryData.h new file mode 100644 index 00000000..6bc8a66f --- /dev/null +++ b/ports/camomile/source/BinaryData.h @@ -0,0 +1,57 @@ +/* ========================================================================================= + + This is an auto-generated file: Any edits you make may be overwritten! + +*/ + +#pragma once + +namespace BinaryData +{ + extern const char* CreditsAU; + const int CreditsAUSize = 479; + + extern const char* CreditsLV2; + const int CreditsLV2Size = 624; + + extern const char* CreditsVST; + const int CreditsVSTSize = 537; + + extern const char* DejaVuSansMono_ttf; + const int DejaVuSansMono_ttfSize = 340712; + + extern const char* copy_png; + const int copy_pngSize = 4098; + + extern const char* flower_center_png; + const int flower_center_pngSize = 3299; + + extern const char* flower_petals_png; + const int flower_petals_pngSize = 22287; + + extern const char* garbage_png; + const int garbage_pngSize = 5113; + + extern const char* reload_png; + const int reload_pngSize = 8380; + + extern const char* settings_png; + const int settings_pngSize = 12539; + + // Number of elements in the namedResourceList and originalFileNames arrays. + const int namedResourceListSize = 10; + + // Points to the start of a list of resource names. + extern const char* namedResourceList[]; + + // Points to the start of a list of resource filenames. + extern const char* originalFilenames[]; + + // If you provide the name of one of the binary resource variables above, this function will + // return the corresponding data and its size (or a null pointer if the name isn't found). + const char* getNamedResource (const char* resourceNameUTF8, int& dataSizeInBytes); + + // If you provide the name of one of the binary resource variables above, this function will + // return the corresponding original, non-mangled filename (or a null pointer if the name isn't found). + const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8); +} diff --git a/ports/camomile/source/JuceHeader.h b/ports/camomile/source/JuceHeader.h new file mode 100644 index 00000000..5d54fbe1 --- /dev/null +++ b/ports/camomile/source/JuceHeader.h @@ -0,0 +1,31 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + + This is the header file that your files should include in order to get all the + JUCE library headers. You should avoid including the JUCE headers directly in + your own source files, because that wouldn't pick up the correct configuration + options for your app. + +*/ + +#pragma once + +#include "JucePluginMain.h" +#include "BinaryData.h" + +#if ! DONT_SET_USING_JUCE_NAMESPACE + // If your code uses a lot of JUCE classes, then this will obviously save you + // a lot of typing, but can be disabled by setting DONT_SET_USING_JUCE_NAMESPACE. + using namespace juce; +#endif + +#if ! JUCE_DONT_DECLARE_PROJECTINFO +namespace ProjectInfo +{ + const char* const projectName = "CamomileLV2"; + const char* const versionString = "1.0.6"; + const int versionNumber = 0x10006; +} +#endif diff --git a/ports/camomile/source/JucePluginCharacteristics.h b/ports/camomile/source/JucePluginCharacteristics.h new file mode 100644 index 00000000..d20dd419 --- /dev/null +++ b/ports/camomile/source/JucePluginCharacteristics.h @@ -0,0 +1,45 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + + If you want to change any of these values, use the Introjucer to do so, + rather than editing this file directly! + + Any commented-out settings will assume their default values. + +*/ + +#ifndef __JUCE_APPCONFIG_E0XYLT__ +#define __JUCE_APPCONFIG_E0XYLT__ + +//============================================================================== +// Audio plugin settings.. + +#include "PluginConfig.h" + +#define JucePlugin_ManufacturerCode 0x50494755 +#define JucePlugin_IsSynth 0 +#define JucePlugin_IsMidiEffect 0 +#define JucePlugin_WantsMidiInput 1 +#define JucePlugin_ProducesMidiOutput 1 +#define JucePlugin_SilenceInProducesSilenceOut 1 +#define JucePlugin_EditorRequiresKeyboardFocus 1 +#define JucePlugin_VersionCode 0x10006 +#define JucePlugin_VersionString "1.0.6" +#define JucePlugin_VSTUniqueID JucePlugin_PluginCode +#define JucePlugin_VSTCategory kPlugCategEffect +#define JucePlugin_AUMainType kAudioUnitType_Effect +#define JucePlugin_AUSubType JucePlugin_PluginCode +#define JucePlugin_AUManufacturerCode JucePlugin_ManufacturerCode +#define JucePlugin_RTASCategory ePlugInCategory_None +#define JucePlugin_RTASManufacturerCode JucePlugin_ManufacturerCode +#define JucePlugin_RTASProductId JucePlugin_PluginCode + +// #define JucePlugin_LV2Category "DynamicsPlugin" +#define JucePlugin_WantsLV2Latency 1 +#define JucePlugin_WantsLV2Presets 1 +#define JucePlugin_WantsLV2State 1 +#define JucePlugin_WantsLV2TimePos 1 + +#endif // __JUCE_APPCONFIG_E0XYLT__ diff --git a/ports/camomile/source/LibPd/libpd_wrapper/s_libpdmidi.c b/ports/camomile/source/LibPd/libpd_wrapper/s_libpdmidi.c new file mode 100644 index 00000000..f80fe52f --- /dev/null +++ b/ports/camomile/source/LibPd/libpd_wrapper/s_libpdmidi.c @@ -0,0 +1,76 @@ +/* Copyright (c) 1997-2010 Miller Puckette and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "s_stuff.h" +#include "z_libpd.h" +#include "z_hooks.h" + +#define CLAMP(x, low, high) ((x > high) ? high : ((x < low) ? low : x)) +#define CLAMP4BIT(x) CLAMP(x, 0, 0x0f) +#define CLAMP7BIT(x) CLAMP(x, 0, 0x7f) +#define CLAMP8BIT(x) CLAMP(x, 0, 0xff) +#define CLAMP12BIT(x) CLAMP(x, 0, 0x0fff) +#define CLAMP14BIT(x) CLAMP(x, 0, 0x3fff) + +#define CHANNEL ((CLAMP12BIT(port) << 4) | CLAMP4BIT(channel)) + +void outmidi_noteon(int port, int channel, int pitch, int velo) { + if (libpd_noteonhook) + libpd_noteonhook(CHANNEL, CLAMP7BIT(pitch), CLAMP7BIT(velo)); +} + +void outmidi_controlchange(int port, int channel, int ctl, int value) { + if (libpd_controlchangehook) + libpd_controlchangehook(CHANNEL, CLAMP7BIT(ctl), CLAMP7BIT(value)); +} + +void outmidi_programchange(int port, int channel, int value) { + if (libpd_programchangehook) + libpd_programchangehook(CHANNEL, CLAMP7BIT(value)); +} + +void outmidi_pitchbend(int port, int channel, int value) { + if (libpd_pitchbendhook) + libpd_pitchbendhook(CHANNEL, CLAMP14BIT(value) - 8192); // remove offset +} + +void outmidi_aftertouch(int port, int channel, int value) { + if (libpd_aftertouchhook) + libpd_aftertouchhook(CHANNEL, CLAMP7BIT(value)); +} + +void outmidi_polyaftertouch(int port, int channel, int pitch, int value) { + if (libpd_polyaftertouchhook) + libpd_polyaftertouchhook(CHANNEL, CLAMP7BIT(pitch), CLAMP7BIT(value)); +} + +void outmidi_byte(int port, int value) { + if (libpd_midibytehook) + libpd_midibytehook(CLAMP12BIT(port), CLAMP8BIT(value)); +} + +/* tell Pd gui that our list of MIDI APIs is empty */ +#include +void sys_get_midi_apis(char *buf) {strcpy(buf, "{}");} + +// The rest is not relevant to libpd. +void sys_listmididevs(void) {} +void sys_get_midi_params(int *pnmidiindev, int *pmidiindev, + int *pnmidioutdev, int *pmidioutdev) {*pnmidiindev = *pnmidioutdev = 0;} +void sys_open_midi(int nmidiindev, int *midiindev, + int nmidioutdev, int *midioutdev, int enable) {} +void sys_close_midi() {} +void sys_reopen_midi(void) {} +void sys_initmidiqueue(void) {} +void sys_pollmidiqueue(void) {} +void sys_setmiditimediff(double inbuftime, double outbuftime) {} +void glob_midi_setapi(void *dummy, t_floatarg f) {} +void glob_midi_properties(t_pd *dummy, t_floatarg flongform) {} +void glob_midi_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) {} +int sys_mididevnametonumber(int output, const char *name) { return 0; } +void sys_mididevnumbertoname(int output, int devno, char *name, int namesize) {} +void sys_set_midi_api(int api) {} +int sys_midiapi; + diff --git a/ports/camomile/source/LibPd/libpd_wrapper/util/ringbuffer.c b/ports/camomile/source/LibPd/libpd_wrapper/util/ringbuffer.c new file mode 100644 index 00000000..1a3f3c1d --- /dev/null +++ b/ports/camomile/source/LibPd/libpd_wrapper/util/ringbuffer.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2012 Peter Brinkmann (peter.brinkmann@gmail.com) + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + * See https://github.com/libpd/libpd/wiki for documentation + * + */ + +#include "ringbuffer.h" + +#include +#include +#include + +#if __STDC_VERSION__ >= 201112L // use stdatomic if C11 is available + #include + #define SYNC_FETCH(ptr) atomic_fetch_or((_Atomic int *)ptr, 0) + #define SYNC_COMPARE_AND_SWAP(ptr, oldval, newval) \ + atomic_compare_exchange_strong((_Atomic int *)ptr, &oldval, newval) +#else // use platform specfics + #ifdef __APPLE__ // apple atomics + #include + #define SYNC_FETCH(ptr) OSAtomicOr32Barrier(0, (volatile uint32_t *)ptr) + #define SYNC_COMPARE_AND_SWAP(ptr, oldval, newval) \ + OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr) + #elif defined(_WIN32) || defined(_WIN64) // win api atomics + #define SYNC_FETCH(ptr) InterlockedOr(ptr, 0) + #define SYNC_COMPARE_AND_SWAP(ptr, oldval, newval) \ + InterlockedCompareExchange(ptr, oldval, newval) + #else // gcc atomics + #define SYNC_FETCH(ptr) __sync_fetch_and_or(ptr, 0) + #define SYNC_COMPARE_AND_SWAP(ptr, oldval, newval) \ + __sync_val_compare_and_swap(ptr, oldval, newval) + #endif +#endif + +ring_buffer *rb_create(int size) { + if (size & 0xff) return NULL; // size must be a multiple of 256 + ring_buffer *buffer = malloc(sizeof(ring_buffer)); + if (!buffer) return NULL; + buffer->buf_ptr = calloc(size, sizeof(char)); + if (!buffer->buf_ptr) { + free(buffer); + return NULL; + } + buffer->size = size; + buffer->write_idx = 0; + buffer->read_idx = 0; + return buffer; +} + +void rb_free(ring_buffer *buffer) { + free(buffer->buf_ptr); + free(buffer); +} + +int rb_available_to_write(ring_buffer *buffer) { + if (buffer) { + // Note: The largest possible result is buffer->size - 1 because + // we adopt the convention that read_idx == write_idx means that the + // buffer is empty. + int read_idx = SYNC_FETCH(&(buffer->read_idx)); + int write_idx = SYNC_FETCH(&(buffer->write_idx)); + return (buffer->size + read_idx - write_idx - 1) % buffer->size; + } else { + return 0; + } +} + +int rb_available_to_read(ring_buffer *buffer) { + if (buffer) { + int read_idx = SYNC_FETCH(&(buffer->read_idx)); + int write_idx = SYNC_FETCH(&(buffer->write_idx)); + return (buffer->size + write_idx - read_idx) % buffer->size; + } else { + return 0; + } +} + +int rb_write_to_buffer(ring_buffer *buffer, int n, ...) { + if (!buffer) return -1; + int write_idx = buffer->write_idx; // No need for sync in writer thread. + int available = rb_available_to_write(buffer); + va_list args; + va_start(args, n); + int i; + for (i = 0; i < n; ++i) { + const char* src = va_arg(args, const char*); + int len = va_arg(args, int); + available -= len; + if (len < 0 || available < 0) return -1; + if (write_idx + len <= buffer->size) { + memcpy(buffer->buf_ptr + write_idx, src, len); + } else { + int d = buffer->size - write_idx; + memcpy(buffer->buf_ptr + write_idx, src, d); + memcpy(buffer->buf_ptr, src + d, len - d); + } + write_idx = (write_idx + len) % buffer->size; + } + va_end(args); + SYNC_COMPARE_AND_SWAP(&(buffer->write_idx), buffer->write_idx, + write_idx); // Includes memory barrier. + return 0; +} + +int rb_read_from_buffer(ring_buffer *buffer, char *dest, int len) { + if (len == 0) return 0; + if (!buffer || len < 0 || len > rb_available_to_read(buffer)) return -1; + // Note that rb_available_to_read also serves as a memory barrier, and so any + // writes to buffer->buf_ptr that precede the update of buffer->write_idx are + // visible to us now. + int read_idx = buffer->read_idx; // No need for sync in reader thread. + if (read_idx + len <= buffer->size) { + memcpy(dest, buffer->buf_ptr + read_idx, len); + } else { + int d = buffer->size - read_idx; + memcpy(dest, buffer->buf_ptr + read_idx, d); + memcpy(dest + d, buffer->buf_ptr, len - d); + } + SYNC_COMPARE_AND_SWAP(&(buffer->read_idx), buffer->read_idx, + (read_idx + len) % buffer->size); // Includes memory barrier. + return 0; +} diff --git a/ports/camomile/source/LibPd/libpd_wrapper/util/ringbuffer.h b/ports/camomile/source/LibPd/libpd_wrapper/util/ringbuffer.h new file mode 100644 index 00000000..65d9c215 --- /dev/null +++ b/ports/camomile/source/LibPd/libpd_wrapper/util/ringbuffer.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012 Peter Brinkmann (peter.brinkmann@gmail.com) + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + * See https://github.com/libpd/libpd/wiki for documentation + * + */ + +#ifndef __OPENSL_RING_BUFFER_H__ +#define __OPENSL_RING_BUFFER_H__ + +// Simple lock-free ring buffer implementation for one writer thread and one +// consumer thread. +typedef struct ring_buffer { + int size; + char *buf_ptr; + int write_idx; + int read_idx; +} ring_buffer; + +// Creates a ring buffer (returns NULL on failure). +ring_buffer *rb_create(int size); + +// Deletes a ring buffer. +void rb_free(ring_buffer *buffer); + +// Returns the number of bytes that can currently be written; safe to be called +// from any thread. +int rb_available_to_write(ring_buffer *buffer); + +// Returns the number of bytes that can currently be read; safe to be called +// from any thread. +int rb_available_to_read(ring_buffer *buffer); + +// Writes bytes from n sources to the ring buffer (if the ring buffer has +// enough space). The varargs are pairs of type (const char*, int) giving a +// pointer to a buffer and the number of bytes to be copied. Only to be called +// from a single writer thread. +// Returns 0 on success. +int rb_write_to_buffer(ring_buffer *buffer, int n, ...); + +// Reads the given number of bytes fromthe ring buffer to dest if the ring +// buffer has enough data. Only to be called from a single reader thread. +// Returns 0 on success. +int rb_read_from_buffer(ring_buffer *buffer, char *dest, int len); + +#endif diff --git a/ports/camomile/source/LibPd/libpd_wrapper/util/z_print_util.c b/ports/camomile/source/LibPd/libpd_wrapper/util/z_print_util.c new file mode 100644 index 00000000..315a5e53 --- /dev/null +++ b/ports/camomile/source/LibPd/libpd_wrapper/util/z_print_util.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Dan Wilcox (danomatika@gmail.com) & + * Peter Brinkmann (peter.brinkmann@gmail.com) + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + * See https://github.com/libpd/libpd/wiki for documentation + * + */ + +#include "z_print_util.h" + +#include +#include + +t_libpd_printhook libpd_concatenated_printhook = NULL; + +#define PRINT_LINE_SIZE 2048 + +void libpd_set_concatenated_printhook(const t_libpd_printhook hook) { + libpd_concatenated_printhook = hook; +} + +void libpd_print_concatenator(const char *s) { + if (!libpd_concatenated_printhook) return; + + static char concatenated_print_line[PRINT_LINE_SIZE]; + static int len_line = 0; + concatenated_print_line[len_line] = '\0'; + + int len = (int) strlen(s); + while (len_line + len >= PRINT_LINE_SIZE) { + int d = PRINT_LINE_SIZE - 1 - len_line; + strncat(concatenated_print_line, s, d); + libpd_concatenated_printhook(concatenated_print_line); + s += d; + len -= d; + len_line = 0; + concatenated_print_line[0] = '\0'; + } + + strncat(concatenated_print_line, s, len); + len_line += len; + + if (len_line > 0 && concatenated_print_line[len_line - 1] == '\n') { + concatenated_print_line[len_line - 1] = '\0'; + libpd_concatenated_printhook(concatenated_print_line); + len_line = 0; + } +} diff --git a/ports/camomile/source/LibPd/libpd_wrapper/util/z_print_util.h b/ports/camomile/source/LibPd/libpd_wrapper/util/z_print_util.h new file mode 100644 index 00000000..53e1c55e --- /dev/null +++ b/ports/camomile/source/LibPd/libpd_wrapper/util/z_print_util.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 Dan Wilcox (danomatika@gmail.com) & + * Peter Brinkmann (peter.brinkmann@gmail.com) + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + * See https://github.com/libpd/libpd/wiki for documentation + * + */ + +#ifndef __Z_PRINT_UTIL_H__ +#define __Z_PRINT_UTIL_H__ + +#include "z_libpd.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +// Concatenate print messages into single lines before returning them +// to a print hook: ie "hello 123" is sent in 1 part -> "hello 123" +// +// For comparison, the default behavior returns individual words and spaces: +// ie "hello 123" is sent in 3 parts -> "hello", " ", "123" + +// Assign the pointer to your print handler. +EXTERN void libpd_set_concatenated_printhook(const t_libpd_printhook hook); + +// Assign this function pointer to libpd_printhook or libpd_queued_printhook, +// depending on whether you're using queued messages, to intercept and +// concatenate print messages: +// +// libpd_set_printhook(libpd_print_concatenator); +// libpd_set_concatenated_printhook(your_print_handler); +// +// Note: The char pointer argument is only good for the duration of the print +// callback; if you intend to use the argument after the callback has +// returned, you need to make a defensive copy. +// +void libpd_print_concatenator(const char *s); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ports/camomile/source/LibPd/libpd_wrapper/util/z_queued.c b/ports/camomile/source/LibPd/libpd_wrapper/util/z_queued.c new file mode 100644 index 00000000..12bb7477 --- /dev/null +++ b/ports/camomile/source/LibPd/libpd_wrapper/util/z_queued.c @@ -0,0 +1,413 @@ +/* + * Copyright (c) 2012 Peter Brinkmann (peter.brinkmann@gmail.com) + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + * See https://github.com/libpd/libpd/wiki for documentation + * + */ + +#include "z_queued.h" + +#include +#include + +#include "ringbuffer.h" + +t_libpd_printhook libpd_queued_printhook = NULL; +t_libpd_banghook libpd_queued_banghook = NULL; +t_libpd_floathook libpd_queued_floathook = NULL; +t_libpd_symbolhook libpd_queued_symbolhook = NULL; +t_libpd_listhook libpd_queued_listhook = NULL; +t_libpd_messagehook libpd_queued_messagehook = NULL; + +t_libpd_noteonhook libpd_queued_noteonhook = NULL; +t_libpd_controlchangehook libpd_queued_controlchangehook = NULL; +t_libpd_programchangehook libpd_queued_programchangehook = NULL; +t_libpd_pitchbendhook libpd_queued_pitchbendhook = NULL; +t_libpd_aftertouchhook libpd_queued_aftertouchhook = NULL; +t_libpd_polyaftertouchhook libpd_queued_polyaftertouchhook = NULL; +t_libpd_midibytehook libpd_queued_midibytehook = NULL; + +typedef struct _pd_params { + enum { + LIBPD_PRINT, LIBPD_BANG, LIBPD_FLOAT, + LIBPD_SYMBOL, LIBPD_LIST, LIBPD_MESSAGE, + } type; + const char *src; + float x; + const char *sym; + int argc; +} pd_params; + +typedef struct _midi_params { + enum { + LIBPD_NOTEON, LIBPD_CONTROLCHANGE, LIBPD_PROGRAMCHANGE, LIBPD_PITCHBEND, + LIBPD_AFTERTOUCH, LIBPD_POLYAFTERTOUCH, LIBPD_MIDIBYTE + } type; + int midi1; + int midi2; + int midi3; +} midi_params; + +#define BUFFER_SIZE 16384 +#define S_PD_PARAMS sizeof(pd_params) +#define S_MIDI_PARAMS sizeof(midi_params) +#define S_ATOM sizeof(t_atom) + +static ring_buffer *pd_receive_buffer = NULL; +static ring_buffer *midi_receive_buffer = NULL; + +static void receive_print(pd_params *p, char **buffer) { + if (libpd_queued_printhook) { + libpd_queued_printhook(*buffer); + } + *buffer += p->argc; +} + +static void receive_bang(pd_params *p, char **buffer) { + if (libpd_queued_banghook) { + libpd_queued_banghook(p->src); + } +} + +static void receive_float(pd_params *p, char **buffer) { + if (libpd_queued_floathook) { + libpd_queued_floathook(p->src, p->x); + } +} + +static void receive_symbol(pd_params *p, char **buffer) { + if (libpd_queued_symbolhook) { + libpd_queued_symbolhook(p->src, p->sym); + } +} + +static void receive_list(pd_params *p, char **buffer) { + if (libpd_queued_listhook) { + libpd_queued_listhook(p->src, p->argc, (t_atom *) *buffer); + } + *buffer += p->argc * S_ATOM; +} + +static void receive_message(pd_params *p, char **buffer) { + if (libpd_queued_messagehook) { + libpd_queued_messagehook(p->src, p->sym, p->argc, (t_atom *) *buffer); + } + *buffer += p->argc * S_ATOM; +} + +#define LIBPD_WORD_ALIGN 8 + +static void internal_printhook(const char *s) { + static char padding[LIBPD_WORD_ALIGN]; + int len = (int) strlen(s) + 1; // remember terminating null char + int rest = len % LIBPD_WORD_ALIGN; + if (rest) rest = LIBPD_WORD_ALIGN - rest; + int total = len + rest; + if (rb_available_to_write(pd_receive_buffer) >= S_PD_PARAMS + total) { + pd_params p = {LIBPD_PRINT, NULL, 0.0f, NULL, total}; + rb_write_to_buffer(pd_receive_buffer, 3, + (const char *)&p, S_PD_PARAMS, s, len, padding, rest); + } +} + +static void internal_banghook(const char *src) { + if (rb_available_to_write(pd_receive_buffer) >= S_PD_PARAMS) { + pd_params p = {LIBPD_BANG, src, 0.0f, NULL, 0}; + rb_write_to_buffer(pd_receive_buffer, 1, (const char *)&p, S_PD_PARAMS); + } +} + +static void internal_floathook(const char *src, float x) { + if (rb_available_to_write(pd_receive_buffer) >= S_PD_PARAMS) { + pd_params p = {LIBPD_FLOAT, src, x, NULL, 0}; + rb_write_to_buffer(pd_receive_buffer, 1, (const char *)&p, S_PD_PARAMS); + } +} + +static void internal_symbolhook(const char *src, const char *sym) { + if (rb_available_to_write(pd_receive_buffer) >= S_PD_PARAMS) { + pd_params p = {LIBPD_SYMBOL, src, 0.0f, sym, 0}; + rb_write_to_buffer(pd_receive_buffer, 1, (const char *)&p, S_PD_PARAMS); + } +} + +static void internal_listhook(const char *src, int argc, t_atom *argv) { + int n = argc * S_ATOM; + if (rb_available_to_write(pd_receive_buffer) >= S_PD_PARAMS + n) { + pd_params p = {LIBPD_LIST, src, 0.0f, NULL, argc}; + rb_write_to_buffer(pd_receive_buffer, 2, + (const char *)&p, S_PD_PARAMS, (const char *)argv, n); + } +} + +static void internal_messagehook(const char *src, const char* sym, + int argc, t_atom *argv) { + int n = argc * S_ATOM; + if (rb_available_to_write(pd_receive_buffer) >= S_PD_PARAMS + n) { + pd_params p = {LIBPD_MESSAGE, src, 0.0f, sym, argc}; + rb_write_to_buffer(pd_receive_buffer, 2, + (const char *)&p, S_PD_PARAMS, (const char *)argv, n); + } +} + +static void receive_noteon(midi_params *p, char **buffer) { + if (libpd_queued_noteonhook) { + libpd_queued_noteonhook(p->midi1, p->midi2, p->midi3); + } +} + +static void receive_controlchange(midi_params *p, char **buffer) { + if (libpd_queued_controlchangehook) { + libpd_queued_controlchangehook(p->midi1, p->midi2, p->midi3); + } +} + +static void receive_programchange(midi_params *p, char **buffer) { + if (libpd_queued_programchangehook) { + libpd_queued_programchangehook(p->midi1, p->midi2); + } +} + +static void receive_pitchbend(midi_params *p, char **buffer) { + if (libpd_queued_pitchbendhook) { + libpd_queued_pitchbendhook(p->midi1, p->midi2); + } +} + +static void receive_aftertouch(midi_params *p, char **buffer) { + if (libpd_queued_aftertouchhook) { + libpd_queued_aftertouchhook(p->midi1, p->midi2); + } +} + +static void receive_polyaftertouch(midi_params *p, char **buffer) { + if (libpd_queued_polyaftertouchhook) { + libpd_queued_polyaftertouchhook(p->midi1, p->midi2, p->midi3); + } +} + +static void receive_midibyte(midi_params *p, char **buffer) { + if (libpd_queued_midibytehook) { + libpd_queued_midibytehook(p->midi1, p->midi2); + } +} + +static void internal_noteonhook(int channel, int pitch, int velocity) { + if (rb_available_to_write(midi_receive_buffer) >= S_MIDI_PARAMS) { + midi_params p = {LIBPD_NOTEON, channel, pitch, velocity}; + rb_write_to_buffer(midi_receive_buffer, 1, (const char *)&p, S_MIDI_PARAMS); + } +} + +static void internal_controlchangehook(int channel, int controller, int value) { + if (rb_available_to_write(midi_receive_buffer) >= S_MIDI_PARAMS) { + midi_params p = {LIBPD_CONTROLCHANGE, channel, controller, value}; + rb_write_to_buffer(midi_receive_buffer, 1, (const char *)&p, S_MIDI_PARAMS); + } +} + +static void internal_programchangehook(int channel, int value) { + if (rb_available_to_write(midi_receive_buffer) >= S_MIDI_PARAMS) { + midi_params p = {LIBPD_PROGRAMCHANGE, channel, value, 0}; + rb_write_to_buffer(midi_receive_buffer, 1, (const char *)&p, S_MIDI_PARAMS); + } +} + +static void internal_pitchbendhook(int channel, int value) { + if (rb_available_to_write(midi_receive_buffer) >= S_MIDI_PARAMS) { + midi_params p = {LIBPD_PITCHBEND, channel, value, 0}; + rb_write_to_buffer(midi_receive_buffer, 1, (const char *)&p, S_MIDI_PARAMS); + } +} + +static void internal_aftertouchhook(int channel, int value) { + if (rb_available_to_write(midi_receive_buffer) >= S_MIDI_PARAMS) { + midi_params p = {LIBPD_AFTERTOUCH, channel, value, 0}; + rb_write_to_buffer(midi_receive_buffer, 1, (const char *)&p, S_MIDI_PARAMS); + } +} + +static void internal_polyaftertouchhook(int channel, int pitch, int value) { + if (rb_available_to_write(midi_receive_buffer) >= S_MIDI_PARAMS) { + midi_params p = {LIBPD_POLYAFTERTOUCH, channel, pitch, value}; + rb_write_to_buffer(midi_receive_buffer, 1, (const char *)&p, S_MIDI_PARAMS); + } +} + +static void internal_midibytehook(int port, int byte) { + if (rb_available_to_write(midi_receive_buffer) >= S_MIDI_PARAMS) { + midi_params p = {LIBPD_MIDIBYTE, port, byte, 0}; + rb_write_to_buffer(midi_receive_buffer, 1, (const char *)&p, S_MIDI_PARAMS); + } +} + +void libpd_set_queued_printhook(const t_libpd_printhook hook) { + libpd_queued_printhook = hook; +} + +void libpd_set_queued_banghook(const t_libpd_banghook hook) { + libpd_queued_banghook = hook; +} + +void libpd_set_queued_floathook(const t_libpd_floathook hook) { + libpd_queued_floathook = hook; +} + +void libpd_set_queued_symbolhook(const t_libpd_symbolhook hook) { + libpd_queued_symbolhook = hook; +} + +void libpd_set_queued_listhook(const t_libpd_listhook hook) { + libpd_queued_listhook = hook; +} + +void libpd_set_queued_messagehook(const t_libpd_messagehook hook) { + libpd_queued_messagehook = hook; +} + +void libpd_set_queued_noteonhook(const t_libpd_noteonhook hook) { + libpd_queued_noteonhook = hook; +} + +void libpd_set_queued_controlchangehook(const t_libpd_controlchangehook hook) { + libpd_queued_controlchangehook = hook; +} + +void libpd_set_queued_programchangehook(const t_libpd_programchangehook hook) { + libpd_queued_programchangehook = hook; +} + +void libpd_set_queued_pitchbendhook(const t_libpd_pitchbendhook hook) { + libpd_queued_pitchbendhook = hook; +} + +void libpd_set_queued_aftertouchhook(const t_libpd_aftertouchhook hook) { + libpd_queued_aftertouchhook = hook; +} + +void libpd_set_queued_polyaftertouchhook(const t_libpd_polyaftertouchhook hook) { + libpd_queued_polyaftertouchhook = hook; +} + +void libpd_set_queued_midibytehook(const t_libpd_midibytehook hook) { + libpd_queued_midibytehook = hook; +} + +int libpd_queued_init() { + pd_receive_buffer = rb_create(BUFFER_SIZE); + if (!pd_receive_buffer) return -1; + midi_receive_buffer = rb_create(BUFFER_SIZE); + if (!midi_receive_buffer) return -1; + + libpd_set_printhook(internal_printhook); + libpd_set_banghook(internal_banghook); + libpd_set_floathook(internal_floathook); + libpd_set_symbolhook(internal_symbolhook); + libpd_set_listhook(internal_listhook); + libpd_set_messagehook(internal_messagehook); + + libpd_set_noteonhook(internal_noteonhook); + libpd_set_controlchangehook(internal_controlchangehook); + libpd_set_programchangehook(internal_programchangehook); + libpd_set_pitchbendhook(internal_pitchbendhook); + libpd_set_aftertouchhook(internal_aftertouchhook); + libpd_set_polyaftertouchhook(internal_polyaftertouchhook); + libpd_set_midibytehook(internal_midibytehook); + + libpd_init(); + return 0; +} + +void libpd_queued_release() { + rb_free(pd_receive_buffer); + rb_free(midi_receive_buffer); +} + +void libpd_queued_receive_pd_messages() { + size_t available = rb_available_to_read(pd_receive_buffer); + if (!available) return; + static char temp_buffer[BUFFER_SIZE]; + rb_read_from_buffer(pd_receive_buffer, temp_buffer, (int) available); + char *end = temp_buffer + available; + char *buffer = temp_buffer; + while (buffer < end) { + pd_params *p = (pd_params *)buffer; + buffer += S_PD_PARAMS; + switch (p->type) { + case LIBPD_PRINT: { + receive_print(p, &buffer); + break; + } + case LIBPD_BANG: { + receive_bang(p, &buffer); + break; + } + case LIBPD_FLOAT: { + receive_float(p, &buffer); + break; + } + case LIBPD_SYMBOL: { + receive_symbol(p, &buffer); + break; + } + case LIBPD_LIST: { + receive_list(p, &buffer); + break; + } + case LIBPD_MESSAGE: { + receive_message(p, &buffer); + break; + } + default: + break; + } + } +} + +void libpd_queued_receive_midi_messages() { + size_t available = rb_available_to_read(midi_receive_buffer); + if (!available) return; + static char temp_buffer[BUFFER_SIZE]; + rb_read_from_buffer(midi_receive_buffer, temp_buffer, (int) available); + char *end = temp_buffer + available; + char *buffer = temp_buffer; + while (buffer < end) { + midi_params *p = (midi_params *)buffer; + buffer += S_MIDI_PARAMS; + switch (p->type) { + case LIBPD_NOTEON: { + receive_noteon(p, &buffer); + break; + } + case LIBPD_CONTROLCHANGE: { + receive_controlchange(p, &buffer); + break; + } + case LIBPD_PROGRAMCHANGE: { + receive_programchange(p, &buffer); + break; + } + case LIBPD_PITCHBEND: { + receive_pitchbend(p, &buffer); + break; + } + case LIBPD_AFTERTOUCH: { + receive_aftertouch(p, &buffer); + break; + } + case LIBPD_POLYAFTERTOUCH: { + receive_polyaftertouch(p, &buffer); + break; + } + case LIBPD_MIDIBYTE: { + receive_midibyte(p, &buffer); + break; + } + default: + break; + } + } +} diff --git a/ports/camomile/source/LibPd/libpd_wrapper/util/z_queued.h b/ports/camomile/source/LibPd/libpd_wrapper/util/z_queued.h new file mode 100644 index 00000000..a1473b6c --- /dev/null +++ b/ports/camomile/source/LibPd/libpd_wrapper/util/z_queued.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2012 Peter Brinkmann (peter.brinkmann@gmail.com) + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + * See https://github.com/libpd/libpd/wiki for documentation + * + */ + +#ifndef __Z_QUEUED_H__ +#define __Z_QUEUED_H__ + +#include "z_libpd.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +EXTERN void libpd_set_queued_printhook(const t_libpd_printhook hook); +EXTERN void libpd_set_queued_banghook(const t_libpd_banghook hook); +EXTERN void libpd_set_queued_floathook(const t_libpd_floathook hook); +EXTERN void libpd_set_queued_symbolhook(const t_libpd_symbolhook hook); +EXTERN void libpd_set_queued_listhook(const t_libpd_listhook hook); +EXTERN void libpd_set_queued_messagehook(const t_libpd_messagehook hook); + +EXTERN void libpd_set_queued_noteonhook(const t_libpd_noteonhook hook); +EXTERN void libpd_set_queued_controlchangehook(const t_libpd_controlchangehook hook); +EXTERN void libpd_set_queued_programchangehook(const t_libpd_programchangehook hook); +EXTERN void libpd_set_queued_pitchbendhook(const t_libpd_pitchbendhook hook); +EXTERN void libpd_set_queued_aftertouchhook(const t_libpd_aftertouchhook hook); +EXTERN void libpd_set_queued_polyaftertouchhook(const t_libpd_polyaftertouchhook hook); +EXTERN void libpd_set_queued_midibytehook(const t_libpd_midibytehook hook); + +int libpd_queued_init(); +void libpd_queued_release(); +void libpd_queued_receive_pd_messages(); +void libpd_queued_receive_midi_messages(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ports/camomile/source/LibPd/libpd_wrapper/x_libpdreceive.c b/ports/camomile/source/LibPd/libpd_wrapper/x_libpdreceive.c new file mode 100644 index 00000000..b9fcdff5 --- /dev/null +++ b/ports/camomile/source/LibPd/libpd_wrapper/x_libpdreceive.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2010 Peter Brinkmann (peter.brinkmann@gmail.com) + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + * See https://github.com/libpd/libpd/wiki for documentation + * + */ + +#include +#include "m_pd.h" +#include "x_libpdreceive.h" +#include "z_libpd.h" +#include "z_hooks.h" + +static t_class *libpdrec_class; + +typedef struct _libpdrec { + t_object x_obj; + t_symbol *x_sym; +} t_libpdrec; + +static void libpdrecbang(t_libpdrec *x) { + if (libpd_banghook) (*libpd_banghook)(x->x_sym->s_name); +} + +static void libpdrecfloat(t_libpdrec *x, t_float f) { + if (libpd_floathook) (*libpd_floathook)(x->x_sym->s_name, f); +} + +static void libpdrecsymbol(t_libpdrec *x, t_symbol *s) { + if (libpd_symbolhook) (*libpd_symbolhook)(x->x_sym->s_name, s->s_name); +} + +static void libpdrecpointer(t_libpdrec *x, t_gpointer *gp) { + // just ignore pointers for now... +} + +static void libpdreclist(t_libpdrec *x, t_symbol *s, int argc, t_atom *argv) { + if (libpd_listhook) (*libpd_listhook)(x->x_sym->s_name, argc, argv); +} + +static void libpdrecanything(t_libpdrec *x, t_symbol *s, + int argc, t_atom *argv) { + if (libpd_messagehook) + (*libpd_messagehook)(x->x_sym->s_name, s->s_name, argc, argv); +} + +static void libpdreceive_free(t_libpdrec *x) { + pd_unbind(&x->x_obj.ob_pd, x->x_sym); +} + +static void *libpdreceive_donew(t_symbol *s) { + t_libpdrec *x; + x = (t_libpdrec *)pd_new(libpdrec_class); + x->x_sym = s; + pd_bind(&x->x_obj.ob_pd, s); + return x; +} + +// This is exposed in the libpd API so must set the lock. +void *libpdreceive_new(t_symbol *s) { + t_libpdrec *x; + sys_lock(); + x = (t_libpdrec *)libpdreceive_donew(s); + sys_unlock(); + return x; +} + +void libpdreceive_setup(void) { + sys_lock(); + libpdrec_class = class_new(gensym("libpd_receive"), + (t_newmethod)libpdreceive_donew, (t_method)libpdreceive_free, + sizeof(t_libpdrec), CLASS_DEFAULT, A_DEFSYM, 0); + class_addbang(libpdrec_class, libpdrecbang); + class_addfloat(libpdrec_class, libpdrecfloat); + class_addsymbol(libpdrec_class, libpdrecsymbol); + class_addpointer(libpdrec_class, libpdrecpointer); + class_addlist(libpdrec_class, libpdreclist); + class_addanything(libpdrec_class, libpdrecanything); + sys_unlock(); +} diff --git a/ports/camomile/source/LibPd/libpd_wrapper/x_libpdreceive.h b/ports/camomile/source/LibPd/libpd_wrapper/x_libpdreceive.h new file mode 100644 index 00000000..90bca7cf --- /dev/null +++ b/ports/camomile/source/LibPd/libpd_wrapper/x_libpdreceive.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2010 Peter Brinkmann (peter.brinkmann@gmail.com) + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + * See https://github.com/libpd/libpd/wiki for documentation + * + */ + +#ifndef __X_LIBPDREC_H__ +#define __X_LIBPDREC_H__ + +#include "m_pd.h" + +void libpdreceive_setup(void); +void *libpdreceive_new(t_symbol *); + +#endif diff --git a/ports/camomile/source/LibPd/libpd_wrapper/z_hooks.c b/ports/camomile/source/LibPd/libpd_wrapper/z_hooks.c new file mode 100644 index 00000000..5418ef8c --- /dev/null +++ b/ports/camomile/source/LibPd/libpd_wrapper/z_hooks.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013 Dan Wilcox (danomatika@gmail.com) + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + * See https://github.com/libpd/libpd/wiki for documentation + * + */ + +#include "z_hooks.h" + +t_libpd_printhook libpd_printhook = NULL; +t_libpd_banghook libpd_banghook = NULL; +t_libpd_floathook libpd_floathook = NULL; +t_libpd_symbolhook libpd_symbolhook = NULL; +t_libpd_listhook libpd_listhook = NULL; +t_libpd_messagehook libpd_messagehook = NULL; + +t_libpd_noteonhook libpd_noteonhook = NULL; +t_libpd_controlchangehook libpd_controlchangehook = NULL; +t_libpd_programchangehook libpd_programchangehook = NULL; +t_libpd_pitchbendhook libpd_pitchbendhook = NULL; +t_libpd_aftertouchhook libpd_aftertouchhook = NULL; +t_libpd_polyaftertouchhook libpd_polyaftertouchhook = NULL; +t_libpd_midibytehook libpd_midibytehook = NULL; diff --git a/ports/camomile/source/LibPd/libpd_wrapper/z_hooks.h b/ports/camomile/source/LibPd/libpd_wrapper/z_hooks.h new file mode 100644 index 00000000..1447714c --- /dev/null +++ b/ports/camomile/source/LibPd/libpd_wrapper/z_hooks.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 Dan Wilcox (danomatika@gmail.com) + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + * See https://github.com/libpd/libpd/wiki for documentation + * + */ + +#ifndef __Z_HOOKS_H__ +#define __Z_HOOKS_H__ + +#include "z_libpd.h" + +// the internal hooks +// in a separate file so they can be used throughout the libpd_wrapper sources, +// do *not* include this file in a user-facing header + +extern t_libpd_printhook libpd_printhook; +extern t_libpd_banghook libpd_banghook; +extern t_libpd_floathook libpd_floathook; +extern t_libpd_symbolhook libpd_symbolhook; +extern t_libpd_listhook libpd_listhook; +extern t_libpd_messagehook libpd_messagehook; + +extern t_libpd_noteonhook libpd_noteonhook; +extern t_libpd_controlchangehook libpd_controlchangehook; +extern t_libpd_programchangehook libpd_programchangehook; +extern t_libpd_pitchbendhook libpd_pitchbendhook; +extern t_libpd_aftertouchhook libpd_aftertouchhook; +extern t_libpd_polyaftertouchhook libpd_polyaftertouchhook; +extern t_libpd_midibytehook libpd_midibytehook; + +#endif diff --git a/ports/camomile/source/LibPd/libpd_wrapper/z_libpd.c b/ports/camomile/source/LibPd/libpd_wrapper/z_libpd.c new file mode 100644 index 00000000..f4f1e1ca --- /dev/null +++ b/ports/camomile/source/LibPd/libpd_wrapper/z_libpd.c @@ -0,0 +1,639 @@ +/* + * Copyright (c) 2010 Peter Brinkmann (peter.brinkmann@gmail.com) + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + * See https://github.com/libpd/libpd/wiki for documentation + * + */ + +#include +#include +#include +#include +#include +#ifndef LIBPD_NO_NUMERIC +# include +#endif +#include "z_libpd.h" +#include "x_libpdreceive.h" +#include "z_hooks.h" +#include "s_stuff.h" +#include "m_imp.h" +#include "g_all_guis.h" + +#if PD_MINOR_VERSION < 46 +# define HAVE_SCHED_TICK_ARG +#endif + +#ifdef HAVE_SCHED_TICK_ARG +# define SCHED_TICK(x) sched_tick(x) +#else +# define SCHED_TICK(x) sched_tick() +#endif + +// forward declares +void pd_init(void); +int sys_startgui(const char *libdir); +void sys_stopgui(void); +int sys_pollgui(void); + +// (optional) built in pd externals setup functions +#ifdef LIBPD_EXTRA + void bob_tilde_setup(); + void bonk_tilde_setup(); + void choice_setup(); + void fiddle_tilde_setup(); + void loop_tilde_setup(); + void lrshift_tilde_setup(); + void pique_setup(); + void sigmund_tilde_setup(); + void stdout_setup(); +#endif + +static PERTHREAD t_atom *argv = NULL; +static PERTHREAD t_atom *curr = NULL; +static PERTHREAD int argm = 0; +static PERTHREAD int argc = 0; + +static void *get_object(const char *s) { + t_pd *x = gensym(s)->s_thing; + return x; +} + +// this is called instead of sys_main() to start things +int libpd_init(void) { + static int initialized = 0; + if (initialized) return -1; // only allow init once (for now) + initialized = 1; + signal(SIGFPE, SIG_IGN); + libpd_start_message(32); // allocate array for message assembly + sys_printhook = (t_printhook) libpd_printhook; + // are all these settings necessary? + sys_externalschedlib = 0; + sys_printtostderr = 0; + sys_usestdpath = 0; // don't use pd_extrapath, only sys_searchpath + sys_debuglevel = 0; + sys_noloadbang = 0; + sys_hipriority = 0; + sys_nmidiin = 0; + sys_nmidiout = 0; +#ifdef HAVE_SCHED_TICK_ARG + sys_time = 0; +#endif + pd_init(); + STUFF->st_soundin = NULL; + STUFF->st_soundout = NULL; + STUFF->st_schedblocksize = DEFDACBLKSIZE; + sys_init_fdpoll(); + libpdreceive_setup(); + sys_set_audio_api(API_DUMMY); + STUFF->st_searchpath = NULL; + sys_libdir = gensym(""); +#ifdef LIBPD_EXTRA + bob_tilde_setup(); + bonk_tilde_setup(); + choice_setup(); + fiddle_tilde_setup(); + loop_tilde_setup(); + lrshift_tilde_setup(); + pique_setup(); + sigmund_tilde_setup(); + stdout_setup(); +#endif +#ifndef LIBPD_NO_NUMERIC + setlocale(LC_NUMERIC, "C"); +#endif + return 0; +} + +void libpd_clear_search_path(void) { + sys_lock(); + namelist_free(STUFF->st_searchpath); + STUFF->st_searchpath = NULL; + sys_unlock(); +} + +void libpd_add_to_search_path(const char *s) { + sys_lock(); + STUFF->st_searchpath = namelist_append(STUFF->st_searchpath, s, 0); + sys_unlock(); +} + +void *libpd_openfile(const char *basename, const char *dirname) { + void * retval; + sys_lock(); + pd_globallock(); + retval = (void *)glob_evalfile(NULL, gensym(basename), gensym(dirname)); + pd_globalunlock(); + sys_unlock(); + return retval; +} + +void libpd_closefile(void *x) { + sys_lock(); + pd_free((t_pd *)x); + sys_unlock(); +} + +int libpd_getdollarzero(void *x) { + sys_lock(); + pd_pushsym((t_pd *)x); + int dzero = canvas_getdollarzero(); + pd_popsym((t_pd *)x); + sys_unlock(); + return dzero; +} + +int libpd_init_audio(int inChans, int outChans, int sampleRate) { + int indev[MAXAUDIOINDEV], inch[MAXAUDIOINDEV], + outdev[MAXAUDIOOUTDEV], outch[MAXAUDIOOUTDEV]; + indev[0] = outdev[0] = DEFAULTAUDIODEV; + inch[0] = inChans; + outch[0] = outChans; + sys_lock(); + sys_set_audio_settings(1, indev, 1, inch, + 1, outdev, 1, outch, sampleRate, -1, 1, DEFDACBLKSIZE); + sched_set_using_audio(SCHED_AUDIO_CALLBACK); + sys_reopen_audio(); + sys_unlock(); + return 0; +} + +int libpd_process_raw(const float *inBuffer, float *outBuffer) { + size_t n_in = STUFF->st_inchannels * DEFDACBLKSIZE; + size_t n_out = STUFF->st_outchannels * DEFDACBLKSIZE; + t_sample *p; + size_t i; + sys_lock(); + sys_microsleep(0); + for (p = STUFF->st_soundin, i = 0; i < n_in; i++) { + *p++ = *inBuffer++; + } + memset(STUFF->st_soundout, 0, n_out * sizeof(t_sample)); + SCHED_TICK(pd_this->pd_systime + STUFF->st_time_per_dsp_tick); + for (p = STUFF->st_soundout, i = 0; i < n_out; i++) { + *outBuffer++ = *p++; + } + sys_unlock(); + return 0; +} + +static const t_sample sample_to_short = SHRT_MAX, + short_to_sample = 1.0 / (t_sample) SHRT_MAX; + +#define PROCESS(_x, _y) \ + int i, j, k; \ + t_sample *p0, *p1; \ + sys_lock(); \ + sys_microsleep(0); \ + for (i = 0; i < ticks; i++) { \ + for (j = 0, p0 = STUFF->st_soundin; j < DEFDACBLKSIZE; j++, p0++) { \ + for (k = 0, p1 = p0; k < STUFF->st_inchannels; k++, p1 += DEFDACBLKSIZE) \ + { \ + *p1 = *inBuffer++ _x; \ + } \ + } \ + memset(STUFF->st_soundout, 0, \ + STUFF->st_outchannels*DEFDACBLKSIZE*sizeof(t_sample)); \ + SCHED_TICK(pd_this->pd_systime + STUFF->st_time_per_dsp_tick); \ + for (j = 0, p0 = STUFF->st_soundout; j < DEFDACBLKSIZE; j++, p0++) { \ + for (k = 0, p1 = p0; k < STUFF->st_outchannels; k++, p1 += DEFDACBLKSIZE) \ + { \ + *outBuffer++ = *p1 _y; \ + } \ + } \ + } \ + sys_unlock(); \ + return 0; + +int libpd_process_short(const int ticks, const short *inBuffer, short *outBuffer) { + PROCESS(* short_to_sample, * sample_to_short) +} + +int libpd_process_float(const int ticks, const float *inBuffer, float *outBuffer) { + PROCESS(,) +} + +int libpd_process_double(const int ticks, const double *inBuffer, double *outBuffer) { + PROCESS(,) +} + +#define GETARRAY \ + t_garray *garray = (t_garray *) pd_findbyclass(gensym(name), garray_class); \ + if (!garray) {sys_unlock(); return -1;} \ + +int libpd_arraysize(const char *name) { + int retval; + sys_lock(); + GETARRAY + retval = garray_npoints(garray); + sys_unlock(); + return retval; +} + +#define MEMCPY(_x, _y) \ + GETARRAY \ + if (n < 0 || offset < 0 || offset + n > garray_npoints(garray)) return -2; \ + t_word *vec = ((t_word *) garray_vec(garray)) + offset; \ + int i; \ + for (i = 0; i < n; i++) _x = _y; + +int libpd_read_array(float *dest, const char *name, int offset, int n) { + sys_lock(); + MEMCPY(*dest++, (vec++)->w_float) + sys_unlock(); + return 0; +} + +int libpd_write_array(const char *name, int offset, const float *src, int n) { + sys_lock(); + MEMCPY((vec++)->w_float, *src++) + sys_unlock(); + return 0; +} + +void libpd_set_float(t_atom *v, float x) { + SETFLOAT(v, x); +} + +void libpd_set_symbol(t_atom *v, const char *sym) { + SETSYMBOL(v, gensym(sym)); +} + +int libpd_list(const char *recv, int n, t_atom *v) { + t_pd *dest; + sys_lock(); + dest = get_object(recv); + if (dest == NULL) + { + sys_unlock(); + return -1; + } + pd_list(dest, &s_list, n, v); + sys_unlock(); + return 0; +} + +int libpd_message(const char *recv, const char *msg, int n, t_atom *v) { + t_pd *dest; + sys_lock(); + dest = get_object(recv); + if (dest == NULL) + { + sys_unlock(); + return -1; + } + pd_typedmess(dest, gensym(msg), n, v); + sys_unlock(); + return 0; +} + +int libpd_start_message(int max_length) { + if (max_length > argm) { + t_atom *v = realloc(argv, max_length * sizeof(t_atom)); + if (v) { + argv = v; + argm = max_length; + } else { + return -1; + } + } + argc = 0; + curr = argv; + return 0; +} + +#define ADD_ARG(f) f(curr, x); curr++; argc++; + +void libpd_add_float(float x) { + ADD_ARG(SETFLOAT); +} + +void libpd_add_symbol(const char *s) { + t_symbol *x; + sys_lock(); + x = gensym(s); + sys_unlock(); + ADD_ARG(SETSYMBOL); +} + +int libpd_finish_list(const char *recv) { + return libpd_list(recv, argc, argv); +} + +int libpd_finish_message(const char *recv, const char *msg) { + return libpd_message(recv, msg, argc, argv); +} + +void *libpd_bind(const char *sym) { + t_symbol *x; + sys_lock(); + x = gensym(sym); + sys_unlock(); + return libpdreceive_new(x); +} + +void libpd_unbind(void *p) { + sys_lock(); + pd_free((t_pd *)p); + sys_unlock(); +} + +int libpd_is_float(t_atom *a) { + return (a)->a_type == A_FLOAT; +} + +int libpd_is_symbol(t_atom *a) { + return (a)->a_type == A_SYMBOL; +} + +float libpd_get_float(t_atom *a) { + return (a)->a_w.w_float; +} + +char *libpd_get_symbol(t_atom *a) { + return (a)->a_w.w_symbol->s_name; +} + +t_atom *libpd_next_atom(t_atom *a) { + return a + 1; +} + +void libpd_set_printhook(const t_libpd_printhook hook) { + libpd_printhook = hook; +} + +void libpd_set_banghook(const t_libpd_banghook hook) { + libpd_banghook = hook; +} + +void libpd_set_floathook(const t_libpd_floathook hook) { + libpd_floathook = hook; +} + +void libpd_set_symbolhook(const t_libpd_symbolhook hook) { + libpd_symbolhook = hook; +} + +void libpd_set_listhook(const t_libpd_listhook hook) { + libpd_listhook = hook; +} + +void libpd_set_messagehook(const t_libpd_messagehook hook) { + libpd_messagehook = hook; +} + +int libpd_symbol(const char *recv, const char *sym) { + void *obj; + sys_lock(); + obj = get_object(recv); + if (obj == NULL) + { + sys_unlock(); + return -1; + } + pd_symbol(obj, gensym(sym)); + sys_unlock(); + return 0; +} + +int libpd_float(const char *recv, float x) { + void *obj; + sys_lock(); + obj = get_object(recv); + if (obj == NULL) + { + sys_unlock(); + return -1; + } + pd_float(obj, x); + sys_unlock(); + return 0; +} + +int libpd_bang(const char *recv) { + void *obj; + sys_lock(); + obj = get_object(recv); + if (obj == NULL) + { + sys_unlock(); + return -1; + } + pd_bang(obj); + sys_unlock(); + return 0; +} + +int libpd_blocksize(void) { + return DEFDACBLKSIZE; +} + +int libpd_exists(const char *sym) { + int retval; + sys_lock(); + retval = (get_object(sym) != NULL); + sys_unlock(); + return retval; +} + +#define CHECK_CHANNEL if (channel < 0) return -1; +#define CHECK_PORT if (port < 0 || port > 0x0fff) return -1; +#define CHECK_RANGE_7BIT(v) if (v < 0 || v > 0x7f) return -1; +#define CHECK_RANGE_8BIT(v) if (v < 0 || v > 0xff) return -1; +#define PORT (channel >> 4) +#define CHANNEL (channel & 0x0f) + +int libpd_noteon(int channel, int pitch, int velocity) { + CHECK_CHANNEL + CHECK_RANGE_7BIT(pitch) + CHECK_RANGE_7BIT(velocity) + sys_lock(); + inmidi_noteon(PORT, CHANNEL, pitch, velocity); + sys_unlock(); + return 0; +} + +int libpd_controlchange(int channel, int controller, int value) { + CHECK_CHANNEL + CHECK_RANGE_7BIT(controller) + CHECK_RANGE_7BIT(value) + sys_lock(); + inmidi_controlchange(PORT, CHANNEL, controller, value); + sys_unlock(); + return 0; +} + +int libpd_programchange(int channel, int value) { + CHECK_CHANNEL + CHECK_RANGE_7BIT(value) + sys_lock(); + inmidi_programchange(PORT, CHANNEL, value); + sys_unlock(); + return 0; +} + +int libpd_pitchbend(int channel, int value) { + CHECK_CHANNEL + if (value < -8192 || value > 8191) return -1; + sys_lock(); + inmidi_pitchbend(PORT, CHANNEL, value + 8192); + sys_unlock(); + // Note: For consistency with Pd, we center the output of [pitchin] + // at 8192. + return 0; +} + +int libpd_aftertouch(int channel, int value) { + CHECK_CHANNEL + CHECK_RANGE_7BIT(value) + sys_lock(); + inmidi_aftertouch(PORT, CHANNEL, value); + sys_unlock(); + return 0; +} + +int libpd_polyaftertouch(int channel, int pitch, int value) { + CHECK_CHANNEL + CHECK_RANGE_7BIT(pitch) + CHECK_RANGE_7BIT(value) + sys_lock(); + inmidi_polyaftertouch(PORT, CHANNEL, pitch, value); + sys_unlock(); + return 0; +} + +int libpd_midibyte(int port, int byte) { + CHECK_PORT + CHECK_RANGE_8BIT(byte) + sys_lock(); + inmidi_byte(port, byte); + sys_unlock(); + return 0; +} + +int libpd_sysex(int port, int byte) { + CHECK_PORT + CHECK_RANGE_8BIT(byte) + sys_lock(); + inmidi_sysex(port, byte); + sys_unlock(); + return 0; +} + +int libpd_sysrealtime(int port, int byte) { + CHECK_PORT + CHECK_RANGE_8BIT(byte) + sys_lock(); + inmidi_realtimein(port, byte); + sys_unlock(); + return 0; +} + +void libpd_set_noteonhook(const t_libpd_noteonhook hook) { + libpd_noteonhook = hook; +} + +void libpd_set_controlchangehook(const t_libpd_controlchangehook hook) { + libpd_controlchangehook = hook; +} + +void libpd_set_programchangehook(const t_libpd_programchangehook hook) { + libpd_programchangehook = hook; +} + +void libpd_set_pitchbendhook(const t_libpd_pitchbendhook hook) { + libpd_pitchbendhook = hook; +} + +void libpd_set_aftertouchhook(const t_libpd_aftertouchhook hook) { + libpd_aftertouchhook = hook; +} + +void libpd_set_polyaftertouchhook(const t_libpd_polyaftertouchhook hook) { + libpd_polyaftertouchhook = hook; +} + +void libpd_set_midibytehook(const t_libpd_midibytehook hook) { + libpd_midibytehook = hook; +} + +int libpd_start_gui(char *path) { + int retval; + sys_lock(); + retval = sys_startgui(path); + sys_unlock(); + return retval; +} + +void libpd_stop_gui(void) { + sys_lock(); + sys_stopgui(); + sys_unlock(); +} + +void libpd_poll_gui(void) { + sys_lock(); + sys_pollgui(); + sys_unlock(); +} + +t_pdinstance *libpd_new_instance(void) { +#ifdef PDINSTANCE + return pdinstance_new(); +#else + return 0; +#endif +} + +void libpd_set_instance(t_pdinstance *x) { +#ifdef PDINSTANCE + pd_setinstance(x); +#endif +} + +void libpd_free_instance(t_pdinstance *x) { +#ifdef PDINSTANCE + pdinstance_free(x); +#endif +} + +t_pdinstance *libpd_this_instance(void) { + return pd_this; +} + +t_pdinstance *libpd_get_instance(int index) { +#ifdef PDINSTANCE + if(index < 0 || index >= pd_ninstances) {return 0;} + return pd_instances[index]; +#else + return pd_this; +#endif +} + +int libpd_num_instances(void) { +#ifdef PDINSTANCE + return pd_ninstances; +#else + return 1; +#endif +} + +void libpd_set_verbose(int verbose) { + if (verbose < 0) verbose = 0; + sys_verbose = verbose; +} + +int libpd_get_verbose(void) { + return sys_verbose; +} + +// dummy routines needed because we don't use s_file.c +void glob_loadpreferences(t_pd *dummy, t_symbol *s) {} +void glob_savepreferences(t_pd *dummy, t_symbol *s) {} +void glob_forgetpreferences(t_pd *dummy) {} +void sys_loadpreferences(const char *filename, int startingup) {} +int sys_oktoloadfiles(int done) {return 1;} +void sys_savepreferences(const char *filename) {} // used in s_path.c diff --git a/ports/camomile/source/LibPd/libpd_wrapper/z_libpd.h b/ports/camomile/source/LibPd/libpd_wrapper/z_libpd.h new file mode 100644 index 00000000..2d5ba582 --- /dev/null +++ b/ports/camomile/source/LibPd/libpd_wrapper/z_libpd.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2010 Peter Brinkmann (peter.brinkmann@gmail.com) + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + * See https://github.com/libpd/libpd/wiki for documentation + * + */ + +#ifndef __Z_LIBPD_H__ +#define __Z_LIBPD_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "m_pd.h" + +EXTERN int libpd_init(void); +EXTERN void libpd_clear_search_path(void); +EXTERN void libpd_add_to_search_path(const char *sym); + +EXTERN void *libpd_openfile(const char *basename, const char *dirname); +EXTERN void libpd_closefile(void *p); +EXTERN int libpd_getdollarzero(void *p); + +EXTERN int libpd_blocksize(void); +EXTERN int libpd_init_audio(int inChans, int outChans, int sampleRate); +EXTERN int libpd_process_raw(const float *inBuffer, float *outBuffer); +EXTERN int libpd_process_short(const int ticks, + const short *inBuffer, short *outBuffer); +EXTERN int libpd_process_float(const int ticks, + const float *inBuffer, float *outBuffer); +EXTERN int libpd_process_double(const int ticks, + const double *inBuffer, double *outBuffer); + +EXTERN int libpd_arraysize(const char *name); +// The parameters of the next two functions are inspired by memcpy. +EXTERN int libpd_read_array(float *dest, const char *src, int offset, int n); +EXTERN int libpd_write_array(const char *dest, int offset, const float *src, int n); + +EXTERN int libpd_bang(const char *recv); +EXTERN int libpd_float(const char *recv, float x); +EXTERN int libpd_symbol(const char *recv, const char *sym); + +EXTERN void libpd_set_float(t_atom *v, float x); +EXTERN void libpd_set_symbol(t_atom *v, const char *sym); +EXTERN int libpd_list(const char *recv, int argc, t_atom *argv); +EXTERN int libpd_message(const char *recv, const char *msg, int argc, t_atom *argv); + +EXTERN int libpd_start_message(int max_length); +EXTERN void libpd_add_float(float x); +EXTERN void libpd_add_symbol(const char *sym); +EXTERN int libpd_finish_list(const char *recv); +EXTERN int libpd_finish_message(const char *recv, const char *msg); + +EXTERN int libpd_exists(const char *sym); +EXTERN void *libpd_bind(const char *sym); +EXTERN void libpd_unbind(void *p); + +EXTERN int libpd_is_float(t_atom *a); +EXTERN int libpd_is_symbol(t_atom *a); +EXTERN float libpd_get_float(t_atom *a); +EXTERN char *libpd_get_symbol(t_atom *a); +EXTERN t_atom *libpd_next_atom(t_atom *a); + +typedef void (*t_libpd_printhook)(const char *recv); +typedef void (*t_libpd_banghook)(const char *recv); +typedef void (*t_libpd_floathook)(const char *recv, float x); +typedef void (*t_libpd_symbolhook)(const char *recv, const char *sym); +typedef void (*t_libpd_listhook)(const char *recv, int argc, t_atom *argv); +typedef void (*t_libpd_messagehook)(const char *recv, const char *msg, + int argc, t_atom *argv); + +EXTERN void libpd_set_printhook(const t_libpd_printhook hook); +EXTERN void libpd_set_banghook(const t_libpd_banghook hook); +EXTERN void libpd_set_floathook(const t_libpd_floathook hook); +EXTERN void libpd_set_symbolhook(const t_libpd_symbolhook hook); +EXTERN void libpd_set_listhook(const t_libpd_listhook hook); +EXTERN void libpd_set_messagehook(const t_libpd_messagehook hook); + +EXTERN int libpd_noteon(int channel, int pitch, int velocity); +EXTERN int libpd_controlchange(int channel, int controller, int value); +EXTERN int libpd_programchange(int channel, int value); +EXTERN int libpd_pitchbend(int channel, int value); +EXTERN int libpd_aftertouch(int channel, int value); +EXTERN int libpd_polyaftertouch(int channel, int pitch, int value); +EXTERN int libpd_midibyte(int port, int byte); +EXTERN int libpd_sysex(int port, int byte); +EXTERN int libpd_sysrealtime(int port, int byte); + +typedef void (*t_libpd_noteonhook)(int channel, int pitch, int velocity); +typedef void (*t_libpd_controlchangehook)(int channel, + int controller, int value); +typedef void (*t_libpd_programchangehook)(int channel, int value); +typedef void (*t_libpd_pitchbendhook)(int channel, int value); +typedef void (*t_libpd_aftertouchhook)(int channel, int value); +typedef void (*t_libpd_polyaftertouchhook)(int channel, int pitch, int value); +typedef void (*t_libpd_midibytehook)(int port, int byte); + +EXTERN void libpd_set_noteonhook(const t_libpd_noteonhook hook); +EXTERN void libpd_set_controlchangehook(const t_libpd_controlchangehook hook); +EXTERN void libpd_set_programchangehook(const t_libpd_programchangehook hook); +EXTERN void libpd_set_pitchbendhook(const t_libpd_pitchbendhook hook); +EXTERN void libpd_set_aftertouchhook(const t_libpd_aftertouchhook hook); +EXTERN void libpd_set_polyaftertouchhook(const t_libpd_polyaftertouchhook hook); +EXTERN void libpd_set_midibytehook(const t_libpd_midibytehook hook); + +/// \section GUI + +/// open the current patches within a Pd vanilla GUI +/// requires the path to Pd's main folder that contains bin/, tcl/, etc +/// returns 0 on success +EXTERN int libpd_start_gui(char *path); + +/// stop the Pd vanilla GUI +EXTERN void libpd_stop_gui(void); + +/// update and handle any GUI messages +EXTERN void libpd_poll_gui(void); + +/// \section Multiple Instances + +/// create a new pd instance +/// returns 0 when libpd is not compiled with PDINSTANCE +EXTERN t_pdinstance *libpd_new_instance(void); + +/// set the current pd instance, +/// subsequent libpd calls will affect this instance only +/// does nothing when libpd is not compiled with PDINSTANCE +EXTERN void libpd_set_instance(t_pdinstance *x); + +/// free a pd instance +/// does nothing when libpd is not compiled with PDINSTANCE +EXTERN void libpd_free_instance(t_pdinstance *x); + +/// get the current pd instance +EXTERN t_pdinstance *libpd_this_instance(void); + +/// get a pd instance by index +/// returns 0 if index is out of bounds +/// returns "this" instance when libpd is not compiled with PDINSTANCE +EXTERN t_pdinstance *libpd_get_instance(int index); + +/// get the number of pd instances +/// returns 1 when libpd is not compiled with PDINSTANCE +EXTERN int libpd_num_instances(void); + +/// \section Log Level + +/// set verbose print state: 0 or 1 +EXTERN void libpd_set_verbose(int verbose); + +/// get the verbose print state: 0 or 1 +EXTERN int libpd_get_verbose(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ports/camomile/source/LibPd/pure-data/src/.dir-locals.el b/ports/camomile/source/LibPd/pure-data/src/.dir-locals.el new file mode 100644 index 00000000..113532dd --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/.dir-locals.el @@ -0,0 +1,12 @@ +; see also https://github.com/erdc-cm/petsc-dev/blob/master/.dir-locals.el +( + (nil . ((indent-tabs-mode . nil) + (tab-width . 4) + (fill-column . 80))) + ;; Warn about spaces used for indentation: + (c-mode . ((c-file-style . "bsd") + (c-basic-offset . 4) + (c-comment-only-line-offset . 4) + )) + (haskell-mode . ((eval . (highlight-regexp "^ *")))) + (java-mode . ((c-file-style . "bsd")))) diff --git a/ports/camomile/source/LibPd/pure-data/src/CHANGELOG.txt b/ports/camomile/source/LibPd/pure-data/src/CHANGELOG.txt new file mode 100644 index 00000000..c376ff43 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/CHANGELOG.txt @@ -0,0 +1,261 @@ +This file describes implementation and API changes; stuff more visible to the +user appears in the "release notes" instead. See the bottom of this file +for original notes on source style and organization. + +0.42.0 + +changed definition of t_float, t_sample, t_floatarg so that they can be +set via #defines (PD_FLOATTYPE, etc). + +0.41.0 + +add support for callback-based audio I/O +headers & code changed to use t_float or t_sample instead of float (patches +by zmoelnig). + + +0.40.0 + +0.39.0 + +canvas_dspstate and signalinlet_new() exported to m_pd.h + +new function verbose() added to m_pd.h + +0.38.0 + +finally figured out how to do "-enable-", etc., flags in the configure +script correctly. + +The scheduler now has a hook (set_so you can add polling routines) : + sys_idlehook(). + +I'm now uploading directly to CVS repository ("main" and "stable_0_38" +branches.) There are still problems keeping CVS's and my versions of +portaudio the same (CVS bashes the "ident" lines). + +t_int to int in binbuf_addv prototype + +64-bit fix to externs makefiles + +Pd now uses portaudio out-of-the-box; customized files are moved to +"src" directory. + +All "tags" are printf'd as %lx to make 64-bit safe. + +GUI queueing mechanism added: sys_queuegui() etc. + +massive rewrite of array code to unify arrays and scalars. + +fixed empty lists automatically to call "bang" method if one is supplied. + +rewrote the "namelist" stuff to facilitate preference saving (s_stuff.h, +s_path.c, s_file.c, s_main.c) + +0.37.2 + +expr() "exp" temporary variables renamed to avoid compilation problems + +0.37.1 + +makefile.in: MANINSTDIR = $(DESTDIR)/$(MANDIR) changed to + $(DESTDIR)/$(INSTALL_PREFIX)/$(MANDIR) (thx. Mathieu Bouchard) + +applied 2 jack patches from Luke Yelavich + +add -fno-strict-aliasing to config script (linux&mac) to improve underflow, +etc., protection + +add underflow protection to vcf~ object; rewrote underflow protection to be +faster in throw~/catch~ and send~/receive~ + +fixed bug in -inchannels/-outchannels arg parsing + +fixed u_main.tk to make "apple" key work to accelerate menus on MACOS + +fooled with MIDI to try to get sysex and other system messages to work. +Needs lots of testing now... + +finally fixed OSS to open audio with NODELAY... also cleared dup-on-exec flag. + +bug fix in scalar_properties + +major editions to the IEM GUIs to fix bugs in how "$" variables are handled. +The code still isn't pretty but hopefully at least works now. + +tried to get alsa noninterleaved access to work (needed for RME). Failed +to get my RME card to load under ALSA and gave up for now. + +fixed scalar drawing to fail gracefully when the template canvas disappears + +bug fix in vd~ for very small delays (d_delay.c) + +set up sys_oldtclversion flag to correct for changed text selection +(u_main.tk, s_main.c, g_rtext.c) + +tried again to add "readn" support to s_audio_alsa.c: coded, but failing so far. + +fixed broken octave divider example + +removed "-Werror" from default makefile; fixed configure script to respect +"CFLAGS" environment variable instead. Suggest developers should use +"setenv CFLAGS -Werror". + +added "-alsaadd" flag so people can specify alsa devnames to add to list. +fixed some problems with Pd crashing when ALSA failed to open. + +took out the 2-pixel padding for MSW in g_canvas.g (HORIZBORDER/VERTBORDER) + +went back to s_midi_mmio (portaudio version got assertion errors and anyway +I could never get sysex working in it as I had wanted.) + +Took bug fixes from s_midi_pm.c, s_audio_jack.c, s_inter.c from "devel" branch; +also added "static" flag to configure.in (but the devel configure.in as a whole +doesn't seem to work for OSX, for me at least.) + +Might have fixed a bug where labels disappear in buttons, etc, when saved +and reloaded. + +brought s_audio_alsa.c up to alsa 1.0.0 compatibility + +fixed "-alsaadd" (never worked before) + +fooled with macintosh audio. Fixed some (not all) of the audio I/O APIs +to deal with open failures better (reducing sys_{in,out}channels accordingly) + +In the Alsa API, the synchronization test was too stringent and was loosened +to 3*DACBLKSIZE/2. + +'make install' fixed to deal with 'extra' correctly. + +one more improvement in jack support (guenter) + +make an "nrt" flag so mac can disable pthread_setschedparam call if yu want. + +------------------- original source notes ------------- + +0. structure definition roadmap. First, the containment tree of things +that can be sent messages ("pure data"). (note that t_object and t_text, +and t_graph and t_canvas, should be unified...) + +------------ BFFORE 0.35: --------- +m_pd.h t_pd anything with a class + t_gobj "graphic object" + t_text text object +g_canvas.h + t_glist list of graphic objects +g_canvas.c t_canvas Pd "document" + +------------ AFTER 0.35: --------- +m_pd.h t_pd anything with a class + t_gobj "graphic object" + t_text patchable object, AKA t_object +g_canvas.h t_glist list of graphic objects, AKA t_canvas + +... and other structures: +g_canvas.h t_selection -- linked list of gobjs + t_editor -- editor state, allocated for visible glists +m_imp.h t_methodentry -- method handler + t_widgetbehavior -- class-dependent editing behavior for gobjs + t_parentwidgetbehavior -- objects' behavior on parent window + t_class -- method definitions, instance size, flags, etc. + + +1. C coding style. The source should pass most "warnings" of C compilers +(-Wall on linux, for instance; see the makefile.) Some informalities +are intentional, for instance the loose use of function prototypes (see +below) and uncast conversions from longer to shorter numerical formats. +The code doesn't respect "const" yet. + +1.1. Prefixes in structure elements. The names of structure elements always +have a K&R-style prefix, as in ((t_atom)x)->a_type, where the "a_" prefix +indicates "atom." This is intended to enhance readability (although the +convention arose from a limitation of early C compilers.) Common prefixes are +"w_" (word), "a_" (atom), "s_" (symbol), "ob_" (object), "te_" (text object), +"g_" (graphical object), and "gl_" (glist, a list of graphical objects). Also, +global symbols sometimes get prefixes, as in "s_float" (the symbol whose string +is "float). Typedefs are prefixed by "t_". Most _private_ structures, i.e., +structures whose definitions appear in a ".c" file, are prefixed by "x_". + +1.2. Function arguments. Many functions take as their first +argument a pointer named "x", which is a pointer to a structure suggested +by the function prefix; e.g., canvas_dirty(x, n) where "x" points to a canvas +(t_canvas *x). + +1.3. Function Prototypes. Functions which are used in at least two different +files (besides where they originate) are prototyped in the appropriate include +file. Functions which are provided in one file and used in one other are +prototyped right where they are used. This is just to keep the size of the +".h" files down for readability's sake. + +1.4. Whacko private terminology. Some terms are lifted from other historically +relevant programs, notably "ugen" (which is just a tilde object; see d_ugen.c.) + +1.5. Spacing. Tabs are 8 spaces; indentation is 4 spaces. Indenting +curly brackets are by themselves on their own lines, as in: + + if (x) + { + x = 0; + } + +Lines should fit within 80 spaces. + +2. Max patch-level compatibility. "Import" and "Export" functions are +provided which aspire to strict compatibility with 0.26 patches (ISPW version), +but which don't get anywhere close to that yet. Where possible, features +appearing on the Mac will comeday also be provided; for instance, the connect +message on the Mac offers segmented patch cords; these will devolve into +straight lines in Pd. Many, many UI objects in Opcode Max will not appear in +Pd, at least at first. + +3. Compatibility with Max 0.26 "externs", i.e., source-level compatibility. Pd +objects follow the style of 0.26 objects as closely as possible, making +exceptions in cases where the 0.26 model is clearly deficient. These are: + +3.1. Anything involving the MacIntosh "Handle" data type is changed to use +char * or void * instead. + +3.2. Pd passes true single-precision floating-point arguments to methods; +Max uses double. +Typedefs are provided: + t_floatarg, t_intarg for arguments passed by the message system + t_float, t_int for the "word" union (in atoms, for example.) + +3.3. Badly-named entities got name changes: + + w_long --> w_int (in the "union word" structure) + +3.4. Many library functions are renamed and have different arguments; +I hope to provide an include file to alias them when compiling Max externs. + +4. Function name prefixes. +Many function names have prefixes which indicate what "package" they belong +to. The exceptions are: + typedmess, vmess, getfn, gensym (m_class.c) + getbytes, freebytes, resizebytes (m_memory.c) + post, error, bug (s_print.c) +which are all frequently called and which don't fit into simple categories. +Important packages are: +(pd-gui:) pdgui -- everything +(pd:) pd -- functions common to all "pd" objects + obj -- fuctions common to all "patchable" objects ala Max + sys -- "system" level functions + binbuf -- functions manipulating binbufs + class -- functions manipulating classes + (other) -- functions common to the named Pd class + +5. Source file prefixes. +PD: +s system interface +m message system +g graphics stuff +d DSP objects +x control objects +z other + +PD-GUI: +t TK front end + + + diff --git a/ports/camomile/source/LibPd/pure-data/src/Makefile.am b/ports/camomile/source/LibPd/pure-data/src/Makefile.am new file mode 100644 index 00000000..6434bf4c --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/Makefile.am @@ -0,0 +1,409 @@ +######################################### +##### Defaults & Paths ##### + +AUTOMAKE_OPTIONS = foreign +CLEANFILES= + +bin_SCRIPTS = +noinst_SCRIPTS = + +pd_CFLAGS = -DPD -DINSTALL_PREFIX=\"$(prefix)\" -DPD_INTERNAL +pd_LDFLAGS = +pd_LDADD = + +# there are pd_* and pd_*_core variables as we need different flags on Windows +# for the DLL and the EXE, other OSes simply set pd_* = $(pd_*_core) later +# also, the "_core" suffix is used as this keeps automake from thinking these +# are library or binary variables since we only need them as placeholders +pd_LDFLAGS_core = +pd_LDADD_core = + +pdsend_CFLAGS = +pdreceive_CFLAGS = +pd_watchdog_CFLAGS = +LIBS = @LIBS@ + +SUFFIXES = .@EXTENSION@ .@SHARED_LIB@ + +######################################### +##### Files, Binaries, & Libs ##### + +# pd core & utils +bin_PROGRAMS = pd pdsend pdreceive + +pdsend_SOURCES = u_pdsend.c +pdreceive_SOURCES = u_pdreceive.c +pd_watchdog_SOURCES = s_watchdog.c + +# on Windows, pd.exe contains only s_entry.c and links against pd.dll +# (where all the logic resides), that's why we have to split the sources +# (only to later merge them again for non-Windows systems) +pd_SOURCES = s_entry.c +pd_SOURCES_core = \ + d_arithmetic.c \ + d_array.c \ + d_ctl.c \ + d_dac.c \ + d_delay.c \ + d_fft.c \ + d_filter.c \ + d_global.c \ + d_math.c \ + d_misc.c \ + d_osc.c \ + d_resample.c \ + d_soundfile.c \ + d_ugen.c \ + g_all_guis.c \ + g_array.c \ + g_bang.c \ + g_canvas.c \ + g_clone.c \ + g_editor.c \ + g_graph.c \ + g_guiconnect.c \ + g_hdial.c \ + g_hslider.c \ + g_io.c \ + g_mycanvas.c \ + g_numbox.c \ + g_readwrite.c \ + g_rtext.c \ + g_scalar.c \ + g_template.c \ + g_text.c \ + g_toggle.c \ + g_traversal.c \ + g_vdial.c \ + g_vslider.c \ + g_vumeter.c \ + m_atom.c \ + m_binbuf.c \ + m_class.c \ + m_conf.c \ + m_glob.c \ + m_memory.c \ + m_obj.c \ + m_pd.c \ + m_sched.c \ + s_audio.c \ + s_file.c \ + s_inter.c \ + s_loader.c \ + s_main.c \ + s_midi.c \ + s_path.c \ + s_print.c \ + s_utf8.c \ + x_acoustics.c \ + x_arithmetic.c \ + x_array.c \ + x_connective.c \ + x_gui.c \ + x_interface.c \ + x_list.c \ + x_midi.c \ + x_misc.c \ + x_net.c \ + x_scalar.c \ + x_text.c \ + x_time.c \ + x_vexp.c \ + x_vexp_fun.c \ + x_vexp_if.c + +# pd-watchdog and "local" pd symlink location for tcl scripts +libpdbindir = $(pkglibdir)/bin + +# these install to ${includedir}/pd +pkginclude_HEADERS = m_pd.h m_imp.h g_canvas.h s_stuff.h g_all_guis.h x_vexp.h +# compatibility: m_pd.h also goes into ${includedir}/ +include_HEADERS = m_pd.h +noinst_HEADERS = g_all_guis.h s_audio_alsa.h s_audio_paring.h s_utf8.h x_vexp.h + +# we want these in the dist tarball +EXTRA_DIST = CHANGELOG.txt notes.txt pd.ico pd.rc \ + makefile.gnu makefile.mac makefile.mingw makefile.msvc \ + s_audio_audiounit.c s_audio_esd.c + +# add WISH define if it's set +WISH=@WISH@ +WISHDEFINE=$(if $(WISH),-DWISH='"$(WISH)"') +pd_CFLAGS += $(WISHDEFINE) + +######################################### +##### Configurations Per Library ##### + +##### Advanced Linux Sound Architecture ##### +if ALSA +pd_CFLAGS += -DUSEAPI_ALSA +pd_LDADD_core += @ALSA_LIBS@ +pd_SOURCES_core += s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c +endif + +##### OSX CoreAudio ##### +# needed by PortAudio on OSX +if COREAUDIO +LIBS += -framework CoreAudio -framework CoreMIDI \ + -framework AudioUnit -framework AudioToolbox +endif + +##### Jack Audio Connection Kit ##### +# TODO support Jack xrun +if JACK +pd_CFLAGS += -DUSEAPI_JACK -DJACK_XRUN +pd_SOURCES_core += s_audio_jack.c + +if JACK_FRAMEWORK +# link to Jackmp.framework on macOS +pd_LDFLAGS_core += -weak_framework Jackmp +else +# link to Jack discovered by configure +pd_LDADD_core += @JACK_LIBS@ +endif + +endif + +##### GNU/Linux Open Sound System ##### +if OSS +pd_CFLAGS += -DUSEAPI_OSS +pd_SOURCES_core += s_audio_oss.c s_midi_oss.c +endif + +##### Windows MultiMedia (File) I/O ##### +if MMIO +pd_CFLAGS += -DUSEAPI_MMIO +pd_SOURCES_core += s_audio_mmio.c +endif + +##### PortAudio ##### +if PORTAUDIO +pd_CFLAGS += -DUSEAPI_PORTAUDIO +pd_SOURCES_core += s_audio_pa.c s_audio_paring.c + +if LOCAL_PORTAUDIO +# link the included portaudio which is built as a static lib +AM_CPPFLAGS += -I$(top_srcdir)/portaudio/portaudio/include +pd_LDADD_core += $(top_builddir)/portaudio/libportaudio.a +else +# link the system's portaudio +pd_LDADD_core += -lportaudio +endif + +# need Carbon framework for PA on Mac +if MACOSX +LIBS += -framework Carbon +endif + +endif + +##### ASIO ##### +# ASIO needs to go after PORTAUDIO in order for it to link properly +if ASIO +# always Windows +pd_LDADD_core += $(top_builddir)/asio/libasio.a +endif + +##### PortMidi ##### +if PORTMIDI +pd_SOURCES_core += s_midi_pm.c + +if LOCAL_PORTMIDI +# link the included portmidi which is built as a static lib +AM_CPPFLAGS += \ + -I$(top_srcdir)/portmidi/portmidi/pm_common \ + -I$(top_srcdir)/portmidi/portmidi/porttime +pd_LDADD_core += $(top_builddir)/portmidi/libportmidi.a +else +# link the system's portmidi +pd_LDADD_core += -lportmidi +endif + +# need Carbon framework for PM on Mac +if MACOSX +LIBS += -framework CoreFoundation -framework Carbon +endif + +endif + +##### NO API? ##### +# if no audio or midi api was detected/specified, fall back to dummy apis +# ie. GNU/HURD, IPHONEOS, ... have no MIDI (not even OSS) +if AUDIO_DUMMY +pd_CFLAGS += -DUSEAPI_DUMMY +pd_SOURCES_core += s_audio_dummy.c +endif +if MIDI_DUMMY +pd_CFLAGS += -DUSEAPI_MIDIDUMMY +pd_SOURCES_core += s_midi_dummy.c +endif + +##### FFTW fft library ##### +if FFTW +pd_SOURCES_core += d_fft_fftw.c +else +pd_SOURCES_core += d_fft_fftsg.c +endif + +######################################### +##### Configurations Per Platform ##### + +##### GNU/Hurd ##### +if HURD + +# install watchdog to $(libdir)/pd/bin as it's not a user facing program +libpdbin_PROGRAMS = pd-watchdog + +# this flag has to have a single leading "-" for libtool, even though ld uses +# --export-dynamic, and libtool sends -Wl,--export-dynamic to ld... +pd_LDFLAGS_core += -export-dynamic + +# on Ubuntu/Karmic 9.10, it doesn't seem to find libm, so force it +pd_LDFLAGS_core += $(LIBM) + +# force linking to pthread, which should really be done with some autotools way +pd_LDFLAGS_core += -lpthread + +# force linking to dl, which should really be done with some autotools way +pd_LDFLAGS_core += -ldl + +endif + +##### GNU/Linux ##### +if LINUX + +# install watchdog to $(libdir)/pd/bin as it's not a user facing program +libpdbin_PROGRAMS = pd-watchdog + +# this flag has to have a single leading "-" for libtool, even though ld uses +# --export-dynamic, and libtool sends -Wl,--export-dynamic to ld... +pd_LDFLAGS_core += -export-dynamic + +# on Ubuntu/Karmic 9.10, it doesn't seem to find libm, so force it +pd_LDFLAGS_core += $(LIBM) + +endif + +##### Apple Mac OSX ##### +if MACOSX + +# install watchdog to $(libdir)/pd/bin as it's not a user facing program +libpdbin_PROGRAMS = pd-watchdog + +# kludge, should use auto macro __APPLE__ +# but who knows what externals rely on this +pd_CFLAGS += -DMACOSX + +# for dynamic loading & threading +LIBS += -ldl -lm -lpthread + +endif + +##### Windows ##### +if WINDOWS + +# win32 sockets, multimedia, and all that +LIBS += -lwsock32 -lwinmm -lole32 -static-libgcc -static-libstdc++ + +bin_SCRIPTS += pd.dll pd.lib pd.def pd.com +CLEANFILES += pd.dll pd.lib pd.def pd.com +noinst_SCRIPTS += libpd.a +CLEANFILES += libpd.a +CLEANFILES += pd.res + +# hide the console +pd_LDFLAGS += -mwindows +# link with ressources and pd.dll import library +pd_LDADD += pd.res pd.lib + +pd_OBJECTS_core = $(pd_SOURCES_core:.c=.o) + +# the variables are taken from the automake Makefile +$(pd_OBJECTS_core) : %.o : %.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(pd_CFLAGS) $(CFLAGS) -c -o $@ $< + +pd.res: pd.rc + $(WINDRES) $< -O coff -o $@ + +# import library for pd.dll. also works with MSVC! +pd.lib: pd.dll + +# another import library (when linking with -lpd), the same as pd.lib. +libpd.a: pd.lib + cp $< $@ + +pd.def: pd.dll + +pd.dll: $(pd_OBJECTS_core) + $(CXX) -shared $(pd_LDFLAGS_core) -o pd.dll \ + $(pd_OBJECTS_core) $(pd_LDADD_core) $(LIBS) \ + -Wl,--export-all-symbols -Wl,--out-implib=pd.lib -Wl,--output-def=pd.def + +# same as pd.exe but without -mwindows and resources +# NOTE: this is a bit ugly. I couldn't figure out how to get automake to build +# two programs with the same basename but different suffix. +pd.com: pd-s_entry.o pd.lib + $(CXX) $(LDFLAGS) -o pd.com pd-s_entry.o $(LIBS) pd.lib + +else +# for other OS, join pd_* with pd_*_core +pd_SOURCES += $(pd_SOURCES_core) +pd_LDADD += $(pd_LDADD_core) +pd_LDFLAGS += $(pd_LDFLAGS_core) +endif + +##### Windows MinGW ##### +if MINGW +# To use SetDllDirectory() in s_loader.c, we need a minimum of Windows +# XP SP1. WINVER isnt' fine-grained enough for that, so we use the +# next minor version of Windows, 5.2. That gives us -DWINVER=0x0502 +pd_CFLAGS += -DWINVER=0x0502 -D_WIN32_WINNT=0x0502 +endif + +######################################### +##### Targets ##### + +.PHONY: convenience-links + +all-local: convenience-links + +# create a bin folder & symlinks to the binaries in order to +# replicate the src/makefile.* build result +convenience-links: $(libpdbin_PROGRAMS) $(bin_PROGRAMS) + $(MKDIR_P) $(top_builddir)/bin + rm -rf $(top_builddir)/bin/pd* + $(LN_S) $(top_builddir)/src/pd$(EXEEXT) $(top_builddir)/bin/pd$(EXEEXT) + $(LN_S) $(top_builddir)/src/pdsend$(EXEEXT) $(top_builddir)/bin/pdsend$(EXEEXT) + $(LN_S) $(top_builddir)/src/pdreceive$(EXEEXT) $(top_builddir)/bin/pdreceive$(EXEEXT) + $(LN_S) $(top_srcdir)/tcl/pd-gui.in $(top_builddir)/bin/pd-gui + test -e $(top_builddir)/src/pd-watchdog$(EXEEXT) && $(LN_S) $(top_builddir)/src/pd-watchdog$(EXEEXT) $(top_builddir)/bin/pd-watchdog$(EXEEXT) || true + +clean-local: + rm -rf $(top_builddir)/bin + +# link to $(libdir)/pd/bin so the tcl scripts can +# launch the core if the gui is started first +# +# We have to make the dir just in case as it may not exist yet & +# we remove any existing symlink if doing a repeated install. +install-exec-hook: + $(MKDIR_P) $(DESTDIR)$(libpdbindir) + rm -f $(DESTDIR)$(libpdbindir)/pd + $(LN_S) $(DESTDIR)$(bindir)/pd $(DESTDIR)$(libpdbindir)/pd + +# remove the $(libdir)/pd/bin link +# & +# remove the leftover $(includedir)/pd dir, fail silently on any non-empty dirs +# +# The "|| true" ensures that if the dir is *not* empty, then rmdir does not throw +# an error and stop make. +uninstall-hook: + rm -f $(DESTDIR)$(libpdbindir)/pd + if test -d $(DESTDIR)$(pkgincludedir) ; then \ + rmdir $(DESTDIR)$(pkgincludedir) 2>/dev/null || true ; \ + fi + +# generate Emacs tags +etags: TAGS + etags --append --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" *.tcl diff --git a/ports/camomile/source/LibPd/pure-data/src/d_arithmetic.c b/ports/camomile/source/LibPd/pure-data/src/d_arithmetic.c new file mode 100644 index 00000000..8f2d0529 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_arithmetic.c @@ -0,0 +1,843 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* arithmetic binops (+, -, *, /). +If no creation argument is given, there are two signal inlets for vector/vector +operation; otherwise it's vector/scalar and the second inlet takes a float +to reset the value. +*/ + +#include "m_pd.h" + +/* ----------------------------- plus ----------------------------- */ +static t_class *plus_class, *scalarplus_class; + +typedef struct _plus +{ + t_object x_obj; + t_float x_f; +} t_plus; + +typedef struct _scalarplus +{ + t_object x_obj; + t_float x_f; + t_float x_g; /* inlet value */ +} t_scalarplus; + +static void *plus_new(t_symbol *s, int argc, t_atom *argv) +{ + if (argc > 1) post("+~: extra arguments ignored"); + if (argc) + { + t_scalarplus *x = (t_scalarplus *)pd_new(scalarplus_class); + floatinlet_new(&x->x_obj, &x->x_g); + x->x_g = atom_getfloatarg(0, argc, argv); + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); + } + else + { + t_plus *x = (t_plus *)pd_new(plus_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); + } +} + +t_int *plus_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + while (n--) *out++ = *in1++ + *in2++; + return (w+5); +} + +t_int *plus_perf8(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + for (; n; n -= 8, in1 += 8, in2 += 8, out += 8) + { + t_sample f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3]; + t_sample f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7]; + + t_sample g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3]; + t_sample g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7]; + + out[0] = f0 + g0; out[1] = f1 + g1; out[2] = f2 + g2; out[3] = f3 + g3; + out[4] = f4 + g4; out[5] = f5 + g5; out[6] = f6 + g6; out[7] = f7 + g7; + } + return (w+5); +} + +t_int *scalarplus_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_float f = *(t_float *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + while (n--) *out++ = *in++ + f; + return (w+5); +} + +t_int *scalarplus_perf8(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_float g = *(t_float *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + for (; n; n -= 8, in += 8, out += 8) + { + t_sample f0 = in[0], f1 = in[1], f2 = in[2], f3 = in[3]; + t_sample f4 = in[4], f5 = in[5], f6 = in[6], f7 = in[7]; + + out[0] = f0 + g; out[1] = f1 + g; out[2] = f2 + g; out[3] = f3 + g; + out[4] = f4 + g; out[5] = f5 + g; out[6] = f6 + g; out[7] = f7 + g; + } + return (w+5); +} + +void dsp_add_plus(t_sample *in1, t_sample *in2, t_sample *out, int n) +{ + if (n&7) + dsp_add(plus_perform, 4, in1, in2, out, n); + else + dsp_add(plus_perf8, 4, in1, in2, out, n); +} + +static void plus_dsp(t_plus *x, t_signal **sp) +{ + dsp_add_plus(sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); +} + +static void scalarplus_dsp(t_scalarplus *x, t_signal **sp) +{ + if (sp[0]->s_n&7) + dsp_add(scalarplus_perform, 4, sp[0]->s_vec, &x->x_g, + sp[1]->s_vec, sp[0]->s_n); + else + dsp_add(scalarplus_perf8, 4, sp[0]->s_vec, &x->x_g, + sp[1]->s_vec, sp[0]->s_n); +} + +static void plus_setup(void) +{ + plus_class = class_new(gensym("+~"), (t_newmethod)plus_new, 0, + sizeof(t_plus), 0, A_GIMME, 0); + class_addmethod(plus_class, (t_method)plus_dsp, gensym("dsp"), A_CANT, 0); + CLASS_MAINSIGNALIN(plus_class, t_plus, x_f); + class_sethelpsymbol(plus_class, gensym("sigbinops")); + scalarplus_class = class_new(gensym("+~"), 0, 0, + sizeof(t_scalarplus), 0, 0); + CLASS_MAINSIGNALIN(scalarplus_class, t_scalarplus, x_f); + class_addmethod(scalarplus_class, (t_method)scalarplus_dsp, + gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(scalarplus_class, gensym("sigbinops")); +} + +/* ----------------------------- minus ----------------------------- */ +static t_class *minus_class, *scalarminus_class; + +typedef struct _minus +{ + t_object x_obj; + t_float x_f; +} t_minus; + +typedef struct _scalarminus +{ + t_object x_obj; + t_float x_f; + t_float x_g; +} t_scalarminus; + +static void *minus_new(t_symbol *s, int argc, t_atom *argv) +{ + if (argc > 1) post("-~: extra arguments ignored"); + if (argc) + { + t_scalarminus *x = (t_scalarminus *)pd_new(scalarminus_class); + floatinlet_new(&x->x_obj, &x->x_g); + x->x_g = atom_getfloatarg(0, argc, argv); + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); + } + else + { + t_minus *x = (t_minus *)pd_new(minus_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); + } +} + +t_int *minus_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + while (n--) *out++ = *in1++ - *in2++; + return (w+5); +} + +t_int *minus_perf8(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + for (; n; n -= 8, in1 += 8, in2 += 8, out += 8) + { + t_sample f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3]; + t_sample f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7]; + + t_sample g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3]; + t_sample g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7]; + + out[0] = f0 - g0; out[1] = f1 - g1; out[2] = f2 - g2; out[3] = f3 - g3; + out[4] = f4 - g4; out[5] = f5 - g5; out[6] = f6 - g6; out[7] = f7 - g7; + } + return (w+5); +} + +t_int *scalarminus_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_float f = *(t_float *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + while (n--) *out++ = *in++ - f; + return (w+5); +} + +t_int *scalarminus_perf8(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_float g = *(t_float *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + for (; n; n -= 8, in += 8, out += 8) + { + t_sample f0 = in[0], f1 = in[1], f2 = in[2], f3 = in[3]; + t_sample f4 = in[4], f5 = in[5], f6 = in[6], f7 = in[7]; + + out[0] = f0 - g; out[1] = f1 - g; out[2] = f2 - g; out[3] = f3 - g; + out[4] = f4 - g; out[5] = f5 - g; out[6] = f6 - g; out[7] = f7 - g; + } + return (w+5); +} + +static void minus_dsp(t_minus *x, t_signal **sp) +{ + if (sp[0]->s_n&7) + dsp_add(minus_perform, 4, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); + else + dsp_add(minus_perf8, 4, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); +} + +static void scalarminus_dsp(t_scalarminus *x, t_signal **sp) +{ + if (sp[0]->s_n&7) + dsp_add(scalarminus_perform, 4, sp[0]->s_vec, &x->x_g, + sp[1]->s_vec, sp[0]->s_n); + else + dsp_add(scalarminus_perf8, 4, sp[0]->s_vec, &x->x_g, + sp[1]->s_vec, sp[0]->s_n); +} + +static void minus_setup(void) +{ + minus_class = class_new(gensym("-~"), (t_newmethod)minus_new, 0, + sizeof(t_minus), 0, A_GIMME, 0); + CLASS_MAINSIGNALIN(minus_class, t_minus, x_f); + class_addmethod(minus_class, (t_method)minus_dsp, gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(minus_class, gensym("sigbinops")); + scalarminus_class = class_new(gensym("-~"), 0, 0, + sizeof(t_scalarminus), 0, 0); + CLASS_MAINSIGNALIN(scalarminus_class, t_scalarminus, x_f); + class_addmethod(scalarminus_class, (t_method)scalarminus_dsp, + gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(scalarminus_class, gensym("sigbinops")); +} + +/* ----------------------------- times ----------------------------- */ + +static t_class *times_class, *scalartimes_class; + +typedef struct _times +{ + t_object x_obj; + t_float x_f; +} t_times; + +typedef struct _scalartimes +{ + t_object x_obj; + t_float x_f; + t_float x_g; +} t_scalartimes; + +static void *times_new(t_symbol *s, int argc, t_atom *argv) +{ + if (argc > 1) post("*~: extra arguments ignored"); + if (argc) + { + t_scalartimes *x = (t_scalartimes *)pd_new(scalartimes_class); + floatinlet_new(&x->x_obj, &x->x_g); + x->x_g = atom_getfloatarg(0, argc, argv); + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); + } + else + { + t_times *x = (t_times *)pd_new(times_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); + } +} + +t_int *times_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + while (n--) *out++ = *in1++ * *in2++; + return (w+5); +} + +t_int *times_perf8(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + for (; n; n -= 8, in1 += 8, in2 += 8, out += 8) + { + t_sample f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3]; + t_sample f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7]; + + t_sample g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3]; + t_sample g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7]; + + out[0] = f0 * g0; out[1] = f1 * g1; out[2] = f2 * g2; out[3] = f3 * g3; + out[4] = f4 * g4; out[5] = f5 * g5; out[6] = f6 * g6; out[7] = f7 * g7; + } + return (w+5); +} + +t_int *scalartimes_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_float f = *(t_float *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + while (n--) *out++ = *in++ * f; + return (w+5); +} + +t_int *scalartimes_perf8(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_float g = *(t_float *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + for (; n; n -= 8, in += 8, out += 8) + { + t_sample f0 = in[0], f1 = in[1], f2 = in[2], f3 = in[3]; + t_sample f4 = in[4], f5 = in[5], f6 = in[6], f7 = in[7]; + + out[0] = f0 * g; out[1] = f1 * g; out[2] = f2 * g; out[3] = f3 * g; + out[4] = f4 * g; out[5] = f5 * g; out[6] = f6 * g; out[7] = f7 * g; + } + return (w+5); +} + +static void times_dsp(t_times *x, t_signal **sp) +{ + if (sp[0]->s_n&7) + dsp_add(times_perform, 4, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); + else + dsp_add(times_perf8, 4, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); +} + +static void scalartimes_dsp(t_scalartimes *x, t_signal **sp) +{ + if (sp[0]->s_n&7) + dsp_add(scalartimes_perform, 4, sp[0]->s_vec, &x->x_g, + sp[1]->s_vec, sp[0]->s_n); + else + dsp_add(scalartimes_perf8, 4, sp[0]->s_vec, &x->x_g, + sp[1]->s_vec, sp[0]->s_n); +} + +static void times_setup(void) +{ + times_class = class_new(gensym("*~"), (t_newmethod)times_new, 0, + sizeof(t_times), 0, A_GIMME, 0); + CLASS_MAINSIGNALIN(times_class, t_times, x_f); + class_addmethod(times_class, (t_method)times_dsp, gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(times_class, gensym("sigbinops")); + scalartimes_class = class_new(gensym("*~"), 0, 0, + sizeof(t_scalartimes), 0, 0); + CLASS_MAINSIGNALIN(scalartimes_class, t_scalartimes, x_f); + class_addmethod(scalartimes_class, (t_method)scalartimes_dsp, + gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(scalartimes_class, gensym("sigbinops")); +} + +/* ----------------------------- over ----------------------------- */ +static t_class *over_class, *scalarover_class; + +typedef struct _over +{ + t_object x_obj; + t_float x_f; +} t_over; + +typedef struct _scalarover +{ + t_object x_obj; + t_float x_f; + t_float x_g; +} t_scalarover; + +static void *over_new(t_symbol *s, int argc, t_atom *argv) +{ + if (argc > 1) post("/~: extra arguments ignored"); + if (argc) + { + t_scalarover *x = (t_scalarover *)pd_new(scalarover_class); + floatinlet_new(&x->x_obj, &x->x_g); + x->x_g = atom_getfloatarg(0, argc, argv); + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); + } + else + { + t_over *x = (t_over *)pd_new(over_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); + } +} + +t_int *over_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + while (n--) + { + t_sample f = *in1++, g = *in2++; + *out++ = (g ? f / g : 0); + } + return (w+5); +} + +t_int *over_perf8(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + for (; n; n -= 8, in1 += 8, in2 += 8, out += 8) + { + t_sample f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3]; + t_sample f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7]; + + t_sample g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3]; + t_sample g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7]; + + out[0] = (g0? f0 / g0 : 0); + out[1] = (g1? f1 / g1 : 0); + out[2] = (g2? f2 / g2 : 0); + out[3] = (g3? f3 / g3 : 0); + out[4] = (g4? f4 / g4 : 0); + out[5] = (g5? f5 / g5 : 0); + out[6] = (g6? f6 / g6 : 0); + out[7] = (g7? f7 / g7 : 0); + } + return (w+5); +} + +t_int *scalarover_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_float f = *(t_float *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + if(f) f = 1./f; + while (n--) *out++ = *in++ * f; + return (w+5); +} + +t_int *scalarover_perf8(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_float g = *(t_float *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + if (g) g = 1.f / g; + for (; n; n -= 8, in += 8, out += 8) + { + t_sample f0 = in[0], f1 = in[1], f2 = in[2], f3 = in[3]; + t_sample f4 = in[4], f5 = in[5], f6 = in[6], f7 = in[7]; + + out[0] = f0 * g; out[1] = f1 * g; out[2] = f2 * g; out[3] = f3 * g; + out[4] = f4 * g; out[5] = f5 * g; out[6] = f6 * g; out[7] = f7 * g; + } + return (w+5); +} + +static void over_dsp(t_over *x, t_signal **sp) +{ + if (sp[0]->s_n&7) + dsp_add(over_perform, 4, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); + else + dsp_add(over_perf8, 4, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); +} + +static void scalarover_dsp(t_scalarover *x, t_signal **sp) +{ + if (sp[0]->s_n&7) + dsp_add(scalarover_perform, 4, sp[0]->s_vec, &x->x_g, + sp[1]->s_vec, sp[0]->s_n); + else + dsp_add(scalarover_perf8, 4, sp[0]->s_vec, &x->x_g, + sp[1]->s_vec, sp[0]->s_n); +} + +static void over_setup(void) +{ + over_class = class_new(gensym("/~"), (t_newmethod)over_new, 0, + sizeof(t_over), 0, A_GIMME, 0); + CLASS_MAINSIGNALIN(over_class, t_over, x_f); + class_addmethod(over_class, (t_method)over_dsp, gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(over_class, gensym("sigbinops")); + scalarover_class = class_new(gensym("/~"), 0, 0, + sizeof(t_scalarover), 0, 0); + CLASS_MAINSIGNALIN(scalarover_class, t_scalarover, x_f); + class_addmethod(scalarover_class, (t_method)scalarover_dsp, + gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(scalarover_class, gensym("sigbinops")); +} + +/* ----------------------------- max ----------------------------- */ +static t_class *max_class, *scalarmax_class; + +typedef struct _max +{ + t_object x_obj; + t_float x_f; +} t_max; + +typedef struct _scalarmax +{ + t_object x_obj; + t_float x_f; + t_float x_g; +} t_scalarmax; + +static void *max_new(t_symbol *s, int argc, t_atom *argv) +{ + if (argc > 1) post("max~: extra arguments ignored"); + if (argc) + { + t_scalarmax *x = (t_scalarmax *)pd_new(scalarmax_class); + floatinlet_new(&x->x_obj, &x->x_g); + x->x_g = atom_getfloatarg(0, argc, argv); + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); + } + else + { + t_max *x = (t_max *)pd_new(max_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); + } +} + +t_int *max_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + while (n--) + { + t_sample f = *in1++, g = *in2++; + *out++ = (f > g ? f : g); + } + return (w+5); +} + +t_int *max_perf8(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + for (; n; n -= 8, in1 += 8, in2 += 8, out += 8) + { + t_sample f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3]; + t_sample f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7]; + + t_sample g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3]; + t_sample g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7]; + + out[0] = (f0 > g0 ? f0 : g0); out[1] = (f1 > g1 ? f1 : g1); + out[2] = (f2 > g2 ? f2 : g2); out[3] = (f3 > g3 ? f3 : g3); + out[4] = (f4 > g4 ? f4 : g4); out[5] = (f5 > g5 ? f5 : g5); + out[6] = (f6 > g6 ? f6 : g6); out[7] = (f7 > g7 ? f7 : g7); + } + return (w+5); +} + +t_int *scalarmax_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_float f = *(t_float *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + while (n--) + { + t_sample g = *in++; + *out++ = (f > g ? f : g); + } + return (w+5); +} + +t_int *scalarmax_perf8(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_float g = *(t_float *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + for (; n; n -= 8, in += 8, out += 8) + { + t_sample f0 = in[0], f1 = in[1], f2 = in[2], f3 = in[3]; + t_sample f4 = in[4], f5 = in[5], f6 = in[6], f7 = in[7]; + + out[0] = (f0 > g ? f0 : g); out[1] = (f1 > g ? f1 : g); + out[2] = (f2 > g ? f2 : g); out[3] = (f3 > g ? f3 : g); + out[4] = (f4 > g ? f4 : g); out[5] = (f5 > g ? f5 : g); + out[6] = (f6 > g ? f6 : g); out[7] = (f7 > g ? f7 : g); + } + return (w+5); +} + +static void max_dsp(t_max *x, t_signal **sp) +{ + if (sp[0]->s_n&7) + dsp_add(max_perform, 4, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); + else + dsp_add(max_perf8, 4, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); +} + +static void scalarmax_dsp(t_scalarmax *x, t_signal **sp) +{ + if (sp[0]->s_n&7) + dsp_add(scalarmax_perform, 4, sp[0]->s_vec, &x->x_g, + sp[1]->s_vec, sp[0]->s_n); + else + dsp_add(scalarmax_perf8, 4, sp[0]->s_vec, &x->x_g, + sp[1]->s_vec, sp[0]->s_n); +} + +static void max_setup(void) +{ + max_class = class_new(gensym("max~"), (t_newmethod)max_new, 0, + sizeof(t_max), 0, A_GIMME, 0); + CLASS_MAINSIGNALIN(max_class, t_max, x_f); + class_addmethod(max_class, (t_method)max_dsp, gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(max_class, gensym("sigbinops")); + scalarmax_class = class_new(gensym("max~"), 0, 0, + sizeof(t_scalarmax), 0, 0); + CLASS_MAINSIGNALIN(scalarmax_class, t_scalarmax, x_f); + class_addmethod(scalarmax_class, (t_method)scalarmax_dsp, + gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(scalarmax_class, gensym("sigbinops")); +} + +/* ----------------------------- min ----------------------------- */ +static t_class *min_class, *scalarmin_class; + +typedef struct _min +{ + t_object x_obj; + t_float x_f; +} t_min; + +typedef struct _scalarmin +{ + t_object x_obj; + t_float x_g; + t_float x_f; +} t_scalarmin; + +static void *min_new(t_symbol *s, int argc, t_atom *argv) +{ + if (argc > 1) post("min~: extra arguments ignored"); + if (argc) + { + t_scalarmin *x = (t_scalarmin *)pd_new(scalarmin_class); + floatinlet_new(&x->x_obj, &x->x_g); + x->x_g = atom_getfloatarg(0, argc, argv); + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); + } + else + { + t_min *x = (t_min *)pd_new(min_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); + } +} + +t_int *min_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + while (n--) + { + t_sample f = *in1++, g = *in2++; + *out++ = (f < g ? f : g); + } + return (w+5); +} + +t_int *min_perf8(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + for (; n; n -= 8, in1 += 8, in2 += 8, out += 8) + { + t_sample f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3]; + t_sample f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7]; + + t_sample g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3]; + t_sample g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7]; + + out[0] = (f0 < g0 ? f0 : g0); out[1] = (f1 < g1 ? f1 : g1); + out[2] = (f2 < g2 ? f2 : g2); out[3] = (f3 < g3 ? f3 : g3); + out[4] = (f4 < g4 ? f4 : g4); out[5] = (f5 < g5 ? f5 : g5); + out[6] = (f6 < g6 ? f6 : g6); out[7] = (f7 < g7 ? f7 : g7); + } + return (w+5); +} + +t_int *scalarmin_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_float f = *(t_float *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + while (n--) + { + t_sample g = *in++; + *out++ = (f < g ? f : g); + } + return (w+5); +} + +t_int *scalarmin_perf8(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_float g = *(t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + int n = (int)(w[4]); + for (; n; n -= 8, in += 8, out += 8) + { + t_sample f0 = in[0], f1 = in[1], f2 = in[2], f3 = in[3]; + t_sample f4 = in[4], f5 = in[5], f6 = in[6], f7 = in[7]; + + out[0] = (f0 < g ? f0 : g); out[1] = (f1 < g ? f1 : g); + out[2] = (f2 < g ? f2 : g); out[3] = (f3 < g ? f3 : g); + out[4] = (f4 < g ? f4 : g); out[5] = (f5 < g ? f5 : g); + out[6] = (f6 < g ? f6 : g); out[7] = (f7 < g ? f7 : g); + } + return (w+5); +} + +static void min_dsp(t_min *x, t_signal **sp) +{ + if (sp[0]->s_n&7) + dsp_add(min_perform, 4, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); + else + dsp_add(min_perf8, 4, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); +} + +static void scalarmin_dsp(t_scalarmin *x, t_signal **sp) +{ + if (sp[0]->s_n&7) + dsp_add(scalarmin_perform, 4, sp[0]->s_vec, &x->x_g, + sp[1]->s_vec, sp[0]->s_n); + else + dsp_add(scalarmin_perf8, 4, sp[0]->s_vec, &x->x_g, + sp[1]->s_vec, sp[0]->s_n); +} + +static void min_setup(void) +{ + min_class = class_new(gensym("min~"), (t_newmethod)min_new, 0, + sizeof(t_min), 0, A_GIMME, 0); + CLASS_MAINSIGNALIN(min_class, t_min, x_f); + class_addmethod(min_class, (t_method)min_dsp, gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(min_class, gensym("sigbinops")); + scalarmin_class = class_new(gensym("min~"), 0, 0, + sizeof(t_scalarmin), 0, 0); + CLASS_MAINSIGNALIN(scalarmin_class, t_scalarmin, x_f); + class_addmethod(scalarmin_class, (t_method)scalarmin_dsp, + gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(scalarmin_class, gensym("sigbinops")); +} + +/* ----------------------- global setup routine ---------------- */ +void d_arithmetic_setup(void) +{ + plus_setup(); + minus_setup(); + times_setup(); + over_setup(); + max_setup(); + min_setup(); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/d_array.c b/ports/camomile/source/LibPd/pure-data/src/d_array.c new file mode 100644 index 00000000..74e084ef --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_array.c @@ -0,0 +1,1049 @@ +/* Copyright (c) 1997-1999 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* sampling */ + +/* LATER make tabread4 and tabread~ */ + +#include "m_pd.h" + + +/* ------------------------- tabwrite~ -------------------------- */ + +static t_class *tabwrite_tilde_class; + +typedef struct _tabwrite_tilde +{ + t_object x_obj; + int x_phase; + int x_nsampsintab; + t_word *x_vec; + t_symbol *x_arrayname; + t_float x_f; +} t_tabwrite_tilde; + +static void tabwrite_tilde_tick(t_tabwrite_tilde *x); + +static void *tabwrite_tilde_new(t_symbol *s) +{ + t_tabwrite_tilde *x = (t_tabwrite_tilde *)pd_new(tabwrite_tilde_class); + x->x_phase = 0x7fffffff; + x->x_arrayname = s; + x->x_f = 0; + return (x); +} + +static void tabwrite_tilde_redraw(t_tabwrite_tilde *x) +{ + t_garray *a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class); + if (!a) + bug("tabwrite_tilde_redraw"); + else garray_redraw(a); +} + +static t_int *tabwrite_tilde_perform(t_int *w) +{ + t_tabwrite_tilde *x = (t_tabwrite_tilde *)(w[1]); + t_sample *in = (t_sample *)(w[2]); + int n = (int)(w[3]), phase = x->x_phase, endphase = x->x_nsampsintab; + if (!x->x_vec) goto bad; + + if (endphase > phase) + { + int nxfer = endphase - phase; + t_word *wp = x->x_vec + phase; + if (nxfer > n) nxfer = n; + phase += nxfer; + while (nxfer--) + { + t_sample f = *in++; + if (PD_BIGORSMALL(f)) + f = 0; + (wp++)->w_float = f; + } + if (phase >= endphase) + { + tabwrite_tilde_redraw(x); + phase = 0x7fffffff; + } + x->x_phase = phase; + } + else x->x_phase = 0x7fffffff; +bad: + return (w+4); +} + +static void tabwrite_tilde_set(t_tabwrite_tilde *x, t_symbol *s) +{ + t_garray *a; + + x->x_arrayname = s; + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + { + if (*s->s_name) pd_error(x, "tabwrite~: %s: no such array", + x->x_arrayname->s_name); + x->x_vec = 0; + } + else if (!garray_getfloatwords(a, &x->x_nsampsintab, &x->x_vec)) + { + pd_error(x, "%s: bad template for tabwrite~", x->x_arrayname->s_name); + x->x_vec = 0; + } + else garray_usedindsp(a); +} + +static void tabwrite_tilde_dsp(t_tabwrite_tilde *x, t_signal **sp) +{ + tabwrite_tilde_set(x, x->x_arrayname); + dsp_add(tabwrite_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); +} + +static void tabwrite_tilde_bang(t_tabwrite_tilde *x) +{ + x->x_phase = 0; +} + +static void tabwrite_tilde_start(t_tabwrite_tilde *x, t_floatarg f) +{ + x->x_phase = (f > 0 ? f : 0); +} + +static void tabwrite_tilde_stop(t_tabwrite_tilde *x) +{ + if (x->x_phase != 0x7fffffff) + { + tabwrite_tilde_redraw(x); + x->x_phase = 0x7fffffff; + } +} + +static void tabwrite_tilde_setup(void) +{ + tabwrite_tilde_class = class_new(gensym("tabwrite~"), + (t_newmethod)tabwrite_tilde_new, 0, + sizeof(t_tabwrite_tilde), 0, A_DEFSYM, 0); + CLASS_MAINSIGNALIN(tabwrite_tilde_class, t_tabwrite_tilde, x_f); + class_addmethod(tabwrite_tilde_class, (t_method)tabwrite_tilde_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(tabwrite_tilde_class, (t_method)tabwrite_tilde_set, + gensym("set"), A_SYMBOL, 0); + class_addmethod(tabwrite_tilde_class, (t_method)tabwrite_tilde_stop, + gensym("stop"), 0); + class_addmethod(tabwrite_tilde_class, (t_method)tabwrite_tilde_start, + gensym("start"), A_DEFFLOAT, 0); + class_addbang(tabwrite_tilde_class, tabwrite_tilde_bang); +} + +/* ------------ tabplay~ - non-transposing sample playback --------------- */ + +static t_class *tabplay_tilde_class; + +typedef struct _tabplay_tilde +{ + t_object x_obj; + t_outlet *x_bangout; + int x_phase; + int x_nsampsintab; + int x_limit; + t_word *x_vec; + t_symbol *x_arrayname; + t_clock *x_clock; +} t_tabplay_tilde; + +static void tabplay_tilde_tick(t_tabplay_tilde *x); + +static void *tabplay_tilde_new(t_symbol *s) +{ + t_tabplay_tilde *x = (t_tabplay_tilde *)pd_new(tabplay_tilde_class); + x->x_clock = clock_new(x, (t_method)tabplay_tilde_tick); + x->x_phase = 0x7fffffff; + x->x_limit = 0; + x->x_arrayname = s; + outlet_new(&x->x_obj, &s_signal); + x->x_bangout = outlet_new(&x->x_obj, &s_bang); + return (x); +} + +static t_int *tabplay_tilde_perform(t_int *w) +{ + t_tabplay_tilde *x = (t_tabplay_tilde *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + t_word *wp; + int n = (int)(w[3]), phase = x->x_phase, + endphase = (x->x_nsampsintab < x->x_limit ? + x->x_nsampsintab : x->x_limit), nxfer, n3; + if (!x->x_vec || phase >= endphase) + goto zero; + + nxfer = endphase - phase; + wp = x->x_vec + phase; + if (nxfer > n) + nxfer = n; + n3 = n - nxfer; + phase += nxfer; + while (nxfer--) + *out++ = (wp++)->w_float; + if (phase >= endphase) + { + clock_delay(x->x_clock, 0); + x->x_phase = 0x7fffffff; + while (n3--) + *out++ = 0; + } + else x->x_phase = phase; + + return (w+4); +zero: + while (n--) *out++ = 0; + return (w+4); +} + +static void tabplay_tilde_set(t_tabplay_tilde *x, t_symbol *s) +{ + t_garray *a; + + x->x_arrayname = s; + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + { + if (*s->s_name) pd_error(x, "tabplay~: %s: no such array", + x->x_arrayname->s_name); + x->x_vec = 0; + } + else if (!garray_getfloatwords(a, &x->x_nsampsintab, &x->x_vec)) + { + pd_error(x, "%s: bad template for tabplay~", x->x_arrayname->s_name); + x->x_vec = 0; + } + else garray_usedindsp(a); +} + +static void tabplay_tilde_dsp(t_tabplay_tilde *x, t_signal **sp) +{ + tabplay_tilde_set(x, x->x_arrayname); + dsp_add(tabplay_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); +} + +static void tabplay_tilde_list(t_tabplay_tilde *x, t_symbol *s, + int argc, t_atom *argv) +{ + long start = atom_getfloatarg(0, argc, argv); + long length = atom_getfloatarg(1, argc, argv); + if (start < 0) start = 0; + if (length <= 0) + x->x_limit = 0x7fffffff; + else + x->x_limit = (int)(start + length); + x->x_phase = (int)start; +} + +static void tabplay_tilde_stop(t_tabplay_tilde *x) +{ + x->x_phase = 0x7fffffff; +} + +static void tabplay_tilde_tick(t_tabplay_tilde *x) +{ + outlet_bang(x->x_bangout); +} + +static void tabplay_tilde_free(t_tabplay_tilde *x) +{ + clock_free(x->x_clock); +} + +static void tabplay_tilde_setup(void) +{ + tabplay_tilde_class = class_new(gensym("tabplay~"), + (t_newmethod)tabplay_tilde_new, (t_method)tabplay_tilde_free, + sizeof(t_tabplay_tilde), 0, A_DEFSYM, 0); + class_addmethod(tabplay_tilde_class, (t_method)tabplay_tilde_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(tabplay_tilde_class, (t_method)tabplay_tilde_stop, + gensym("stop"), 0); + class_addmethod(tabplay_tilde_class, (t_method)tabplay_tilde_set, + gensym("set"), A_DEFSYM, 0); + class_addlist(tabplay_tilde_class, tabplay_tilde_list); +} + +/******************** tabread~ ***********************/ + +static t_class *tabread_tilde_class; + +typedef struct _tabread_tilde +{ + t_object x_obj; + int x_npoints; + t_word *x_vec; + t_symbol *x_arrayname; + t_float x_f; +} t_tabread_tilde; + +static void *tabread_tilde_new(t_symbol *s) +{ + t_tabread_tilde *x = (t_tabread_tilde *)pd_new(tabread_tilde_class); + x->x_arrayname = s; + x->x_vec = 0; + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *tabread_tilde_perform(t_int *w) +{ + t_tabread_tilde *x = (t_tabread_tilde *)(w[1]); + t_sample *in = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + int maxindex; + t_word *buf = x->x_vec; + int i; + + maxindex = x->x_npoints - 1; + if(maxindex<0) goto zero; + if (!buf) goto zero; + + for (i = 0; i < n; i++) + { + int index = *in++; + if (index < 0) + index = 0; + else if (index > maxindex) + index = maxindex; + *out++ = buf[index].w_float; + } + return (w+5); + zero: + while (n--) *out++ = 0; + + return (w+5); +} + +static void tabread_tilde_set(t_tabread_tilde *x, t_symbol *s) +{ + t_garray *a; + + x->x_arrayname = s; + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + { + if (*s->s_name) + pd_error(x, "tabread~: %s: no such array", x->x_arrayname->s_name); + x->x_vec = 0; + } + else if (!garray_getfloatwords(a, &x->x_npoints, &x->x_vec)) + { + pd_error(x, "%s: bad template for tabread~", x->x_arrayname->s_name); + x->x_vec = 0; + } + else garray_usedindsp(a); +} + +static void tabread_tilde_dsp(t_tabread_tilde *x, t_signal **sp) +{ + tabread_tilde_set(x, x->x_arrayname); + + dsp_add(tabread_tilde_perform, 4, x, + sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); + +} + +static void tabread_tilde_free(t_tabread_tilde *x) +{ +} + +static void tabread_tilde_setup(void) +{ + tabread_tilde_class = class_new(gensym("tabread~"), + (t_newmethod)tabread_tilde_new, (t_method)tabread_tilde_free, + sizeof(t_tabread_tilde), 0, A_DEFSYM, 0); + CLASS_MAINSIGNALIN(tabread_tilde_class, t_tabread_tilde, x_f); + class_addmethod(tabread_tilde_class, (t_method)tabread_tilde_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(tabread_tilde_class, (t_method)tabread_tilde_set, + gensym("set"), A_SYMBOL, 0); +} + +/******************** tabread4~ ***********************/ + +static t_class *tabread4_tilde_class; + +typedef struct _tabread4_tilde +{ + t_object x_obj; + int x_npoints; + t_word *x_vec; + t_symbol *x_arrayname; + t_float x_f; + t_float x_onset; +} t_tabread4_tilde; + +static void *tabread4_tilde_new(t_symbol *s) +{ + t_tabread4_tilde *x = (t_tabread4_tilde *)pd_new(tabread4_tilde_class); + x->x_arrayname = s; + x->x_vec = 0; + outlet_new(&x->x_obj, gensym("signal")); + floatinlet_new(&x->x_obj, &x->x_onset); + x->x_f = 0; + x->x_onset = 0; + return (x); +} + +static t_int *tabread4_tilde_perform(t_int *w) +{ + t_tabread4_tilde *x = (t_tabread4_tilde *)(w[1]); + t_sample *in = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + int maxindex; + t_word *buf = x->x_vec, *wp; + double onset = x->x_onset; + int i; + + maxindex = x->x_npoints - 3; + if(maxindex<0) goto zero; + + if (!buf) goto zero; + +#if 0 /* test for spam -- I'm not ready to deal with this */ + for (i = 0, xmax = 0, xmin = maxindex, fp = in1; i < n; i++, fp++) + { + t_sample f = *in1; + if (f < xmin) xmin = f; + else if (f > xmax) xmax = f; + } + if (xmax < xmin + x->c_maxextent) xmax = xmin + x->c_maxextent; + for (i = 0, splitlo = xmin+ x->c_maxextent, splithi = xmax - x->c_maxextent, + fp = in1; i < n; i++, fp++) + { + t_sample f = *in1; + if (f > splitlo && f < splithi) goto zero; + } +#endif + + for (i = 0; i < n; i++) + { + double findex = *in++ + onset; + int index = findex; + t_sample frac, a, b, c, d, cminusb; + if (index < 1) + index = 1, frac = 0; + else if (index > maxindex) + index = maxindex, frac = 1; + else frac = findex - index; + wp = buf + index; + a = wp[-1].w_float; + b = wp[0].w_float; + c = wp[1].w_float; + d = wp[2].w_float; + cminusb = c-b; + *out++ = b + frac * ( + cminusb - 0.1666667f * (1.-frac) * ( + (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b) + ) + ); + } + return (w+5); + zero: + while (n--) *out++ = 0; + + return (w+5); +} + +static void tabread4_tilde_set(t_tabread4_tilde *x, t_symbol *s) +{ + t_garray *a; + + x->x_arrayname = s; + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + { + if (*s->s_name) + pd_error(x, "tabread4~: %s: no such array", x->x_arrayname->s_name); + x->x_vec = 0; + } + else if (!garray_getfloatwords(a, &x->x_npoints, &x->x_vec)) + { + pd_error(x, "%s: bad template for tabread4~", x->x_arrayname->s_name); + x->x_vec = 0; + } + else garray_usedindsp(a); +} + +static void tabread4_tilde_dsp(t_tabread4_tilde *x, t_signal **sp) +{ + tabread4_tilde_set(x, x->x_arrayname); + + dsp_add(tabread4_tilde_perform, 4, x, + sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); + +} + +static void tabread4_tilde_free(t_tabread4_tilde *x) +{ +} + +static void tabread4_tilde_setup(void) +{ + tabread4_tilde_class = class_new(gensym("tabread4~"), + (t_newmethod)tabread4_tilde_new, (t_method)tabread4_tilde_free, + sizeof(t_tabread4_tilde), 0, A_DEFSYM, 0); + CLASS_MAINSIGNALIN(tabread4_tilde_class, t_tabread4_tilde, x_f); + class_addmethod(tabread4_tilde_class, (t_method)tabread4_tilde_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(tabread4_tilde_class, (t_method)tabread4_tilde_set, + gensym("set"), A_SYMBOL, 0); +} + +/******************** tabosc4~ ***********************/ + +/* this is all copied from d_osc.c... what include file could this go in? */ +#define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */ + +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) \ + || defined(__OpenBSD__) +#include +#endif + +#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || \ + defined(ANDROID) +#include +#endif + +#ifdef __MINGW32__ +#include +#endif + +#ifdef _MSC_VER +/* _MSVC lacks BYTE_ORDER and LITTLE_ENDIAN */ +#define LITTLE_ENDIAN 0x0001 +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) +#error No byte order defined +#endif + +#if BYTE_ORDER == LITTLE_ENDIAN +# define HIOFFSET 1 +# define LOWOFFSET 0 +#else +# define HIOFFSET 0 /* word offset to find MSB */ +# define LOWOFFSET 1 /* word offset to find LSB */ +#endif + +union tabfudge +{ + double tf_d; + int32_t tf_i[2]; +}; + +static t_class *tabosc4_tilde_class; + +typedef struct _tabosc4_tilde +{ + t_object x_obj; + t_float x_fnpoints; + t_float x_finvnpoints; + t_word *x_vec; + t_symbol *x_arrayname; + t_float x_f; + double x_phase; + t_float x_conv; +} t_tabosc4_tilde; + +static void *tabosc4_tilde_new(t_symbol *s) +{ + t_tabosc4_tilde *x = (t_tabosc4_tilde *)pd_new(tabosc4_tilde_class); + x->x_arrayname = s; + x->x_vec = 0; + x->x_fnpoints = 512.; + x->x_finvnpoints = (1./512.); + outlet_new(&x->x_obj, gensym("signal")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1")); + x->x_f = 0; + return (x); +} + +static t_int *tabosc4_tilde_perform(t_int *w) +{ + t_tabosc4_tilde *x = (t_tabosc4_tilde *)(w[1]); + t_sample *in = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + int normhipart; + union tabfudge tf; + t_float fnpoints = x->x_fnpoints; + int mask = fnpoints - 1; + t_float conv = fnpoints * x->x_conv; + int maxindex; + t_word *tab = x->x_vec, *addr; + int i; + double dphase = fnpoints * x->x_phase + UNITBIT32; + + if (!tab) goto zero; + tf.tf_d = UNITBIT32; + normhipart = tf.tf_i[HIOFFSET]; + +#if 1 + while (n--) + { + t_sample frac, a, b, c, d, cminusb; + tf.tf_d = dphase; + dphase += *in++ * conv; + addr = tab + (tf.tf_i[HIOFFSET] & mask); + tf.tf_i[HIOFFSET] = normhipart; + frac = tf.tf_d - UNITBIT32; + a = addr[0].w_float; + b = addr[1].w_float; + c = addr[2].w_float; + d = addr[3].w_float; + cminusb = c-b; + *out++ = b + frac * ( + cminusb - 0.1666667f * (1.-frac) * ( + (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b) + ) + ); + } +#endif + + tf.tf_d = UNITBIT32 * fnpoints; + normhipart = tf.tf_i[HIOFFSET]; + tf.tf_d = dphase + (UNITBIT32 * fnpoints - UNITBIT32); + tf.tf_i[HIOFFSET] = normhipart; + x->x_phase = (tf.tf_d - UNITBIT32 * fnpoints) * x->x_finvnpoints; + return (w+5); + zero: + while (n--) *out++ = 0; + + return (w+5); +} + +static void tabosc4_tilde_set(t_tabosc4_tilde *x, t_symbol *s) +{ + t_garray *a; + int npoints, pointsinarray; + + x->x_arrayname = s; + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + { + if (*s->s_name) + pd_error(x, "tabosc4~: %s: no such array", x->x_arrayname->s_name); + x->x_vec = 0; + } + else if (!garray_getfloatwords(a, &pointsinarray, &x->x_vec)) + { + pd_error(x, "%s: bad template for tabosc4~", x->x_arrayname->s_name); + x->x_vec = 0; + } + else if ((npoints = pointsinarray - 3) != (1 << ilog2(pointsinarray - 3))) + { + pd_error(x, "%s: number of points (%d) not a power of 2 plus three", + x->x_arrayname->s_name, pointsinarray); + x->x_vec = 0; + garray_usedindsp(a); + } + else + { + x->x_fnpoints = npoints; + x->x_finvnpoints = 1./npoints; + garray_usedindsp(a); + } +} + +static void tabosc4_tilde_ft1(t_tabosc4_tilde *x, t_float f) +{ + x->x_phase = f; +} + +static void tabosc4_tilde_dsp(t_tabosc4_tilde *x, t_signal **sp) +{ + x->x_conv = 1. / sp[0]->s_sr; + tabosc4_tilde_set(x, x->x_arrayname); + + dsp_add(tabosc4_tilde_perform, 4, x, + sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void tabosc4_tilde_setup(void) +{ + tabosc4_tilde_class = class_new(gensym("tabosc4~"), + (t_newmethod)tabosc4_tilde_new, 0, + sizeof(t_tabosc4_tilde), 0, A_DEFSYM, 0); + CLASS_MAINSIGNALIN(tabosc4_tilde_class, t_tabosc4_tilde, x_f); + class_addmethod(tabosc4_tilde_class, (t_method)tabosc4_tilde_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(tabosc4_tilde_class, (t_method)tabosc4_tilde_set, + gensym("set"), A_SYMBOL, 0); + class_addmethod(tabosc4_tilde_class, (t_method)tabosc4_tilde_ft1, + gensym("ft1"), A_FLOAT, 0); +} + +/* ------------------------ tabsend~ ------------------------- */ + +static t_class *tabsend_class; + +typedef struct _tabsend +{ + t_object x_obj; + t_word *x_vec; + int x_graphperiod; + int x_graphcount; + t_symbol *x_arrayname; + t_float x_f; + int x_npoints; +} t_tabsend; + +static void tabsend_tick(t_tabsend *x); + +static void *tabsend_new(t_symbol *s) +{ + t_tabsend *x = (t_tabsend *)pd_new(tabsend_class); + x->x_graphcount = 0; + x->x_arrayname = s; + x->x_f = 0; + return (x); +} + +static t_int *tabsend_perform(t_int *w) +{ + t_tabsend *x = (t_tabsend *)(w[1]); + t_sample *in = (t_sample *)(w[2]); + int n = (int)w[3]; + t_word *dest = x->x_vec; + int i = x->x_graphcount; + if (!x->x_vec) goto bad; + if (n > x->x_npoints) + n = x->x_npoints; + while (n--) + { + t_sample f = *in++; + if (PD_BIGORSMALL(f)) + f = 0; + (dest++)->w_float = f; + } + if (!i--) + { + t_garray *a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class); + if (!a) + bug("tabsend_dsp"); + else garray_redraw(a); + i = x->x_graphperiod; + } + x->x_graphcount = i; +bad: + return (w+4); +} + +static void tabsend_set(t_tabsend *x, t_symbol *s) +{ + t_garray *a; + + x->x_arrayname = s; + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + { + if (*s->s_name) + pd_error(x, "tabsend~: %s: no such array", x->x_arrayname->s_name); + x->x_vec = 0; + } + else if (!garray_getfloatwords(a, &x->x_npoints, &x->x_vec)) + { + pd_error(x, "%s: bad template for tabsend~", x->x_arrayname->s_name); + x->x_vec = 0; + } + else garray_usedindsp(a); +} + +static void tabsend_dsp(t_tabsend *x, t_signal **sp) +{ + int i, vecsize; + int n = sp[0]->s_n; + int ticksper = sp[0]->s_sr/n; + tabsend_set(x, x->x_arrayname); + if (ticksper < 1) ticksper = 1; + x->x_graphperiod = ticksper; + if (x->x_graphcount > ticksper) x->x_graphcount = ticksper; + dsp_add(tabsend_perform, 3, x, sp[0]->s_vec, n); +} + +static void tabsend_setup(void) +{ + tabsend_class = class_new(gensym("tabsend~"), (t_newmethod)tabsend_new, + 0, sizeof(t_tabsend), 0, A_DEFSYM, 0); + CLASS_MAINSIGNALIN(tabsend_class, t_tabsend, x_f); + class_addmethod(tabsend_class, (t_method)tabsend_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(tabsend_class, (t_method)tabsend_set, + gensym("set"), A_SYMBOL, 0); +} + +/* ------------------------ tabreceive~ ------------------------- */ + +static t_class *tabreceive_class; + +typedef struct _tabreceive +{ + t_object x_obj; + t_word *x_vec; + t_symbol *x_arrayname; + int x_npoints; +} t_tabreceive; + +static t_int *tabreceive_perform(t_int *w) +{ + t_tabreceive *x = (t_tabreceive *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)w[3]; + t_word *from = x->x_vec; + if (from) + { + t_int vecsize = x->x_npoints; + if (vecsize > n) + vecsize = n; + while (vecsize--) + *out++ = (from++)->w_float; + vecsize = n - x->x_npoints; + if (vecsize > 0) + while (vecsize--) + *out++ = 0; + } + else while (n--) *out++ = 0; + return (w+4); +} + +static void tabreceive_set(t_tabreceive *x, t_symbol *s) +{ + t_garray *a; + + x->x_arrayname = s; + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + { + if (*s->s_name) + pd_error(x, "tabreceive~: %s: no such array", + x->x_arrayname->s_name); + x->x_vec = 0; + } + else if (!garray_getfloatwords(a, &x->x_npoints, &x->x_vec)) + { + pd_error(x, "%s: bad template for tabreceive~", + x->x_arrayname->s_name); + x->x_vec = 0; + } + else garray_usedindsp(a); +} + +static void tabreceive_dsp(t_tabreceive *x, t_signal **sp) +{ + tabreceive_set(x, x->x_arrayname); + dsp_add(tabreceive_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); +} + +static void *tabreceive_new(t_symbol *s) +{ + t_tabreceive *x = (t_tabreceive *)pd_new(tabreceive_class); + x->x_arrayname = s; + outlet_new(&x->x_obj, &s_signal); + return (x); +} + +static void tabreceive_setup(void) +{ + tabreceive_class = class_new(gensym("tabreceive~"), + (t_newmethod)tabreceive_new, 0, + sizeof(t_tabreceive), 0, A_DEFSYM, 0); + class_addmethod(tabreceive_class, (t_method)tabreceive_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(tabreceive_class, (t_method)tabreceive_set, + gensym("set"), A_SYMBOL, 0); +} + +/* ---------- tabread: control, non-interpolating ------------------------ */ + +static t_class *tabread_class; + +typedef struct _tabread +{ + t_object x_obj; + t_symbol *x_arrayname; +} t_tabread; + +static void tabread_float(t_tabread *x, t_float f) +{ + t_garray *a; + int npoints; + t_word *vec; + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + pd_error(x, "%s: no such array", x->x_arrayname->s_name); + else if (!garray_getfloatwords(a, &npoints, &vec)) + pd_error(x, "%s: bad template for tabread", x->x_arrayname->s_name); + else + { + int n = f; + if (n < 0) n = 0; + else if (n >= npoints) n = npoints - 1; + outlet_float(x->x_obj.ob_outlet, (npoints ? vec[n].w_float : 0)); + } +} + +static void tabread_set(t_tabread *x, t_symbol *s) +{ + x->x_arrayname = s; +} + +static void *tabread_new(t_symbol *s) +{ + t_tabread *x = (t_tabread *)pd_new(tabread_class); + x->x_arrayname = s; + outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void tabread_setup(void) +{ + tabread_class = class_new(gensym("tabread"), (t_newmethod)tabread_new, + 0, sizeof(t_tabread), 0, A_DEFSYM, 0); + class_addfloat(tabread_class, (t_method)tabread_float); + class_addmethod(tabread_class, (t_method)tabread_set, gensym("set"), + A_SYMBOL, 0); +} + +/* ---------- tabread4: control, 4-point interpolation --------------- */ + +static t_class *tabread4_class; + +typedef struct _tabread4 +{ + t_object x_obj; + t_symbol *x_arrayname; +} t_tabread4; + +static void tabread4_float(t_tabread4 *x, t_float f) +{ + t_garray *a; + int npoints; + t_word *vec; + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + pd_error(x, "%s: no such array", x->x_arrayname->s_name); + else if (!garray_getfloatwords(a, &npoints, &vec)) + pd_error(x, "%s: bad template for tabread4", x->x_arrayname->s_name); + else if (npoints < 4) + outlet_float(x->x_obj.ob_outlet, 0); + else if (f <= 1) + outlet_float(x->x_obj.ob_outlet, vec[1].w_float); + else if (f >= npoints - 2) + outlet_float(x->x_obj.ob_outlet, vec[npoints - 2].w_float); + else + { + int n = f; + float a, b, c, d, cminusb, frac; + t_word *wp; + if (n >= npoints - 2) + n = npoints - 3; + wp = vec + n; + frac = f - n; + a = wp[-1].w_float; + b = wp[0].w_float; + c = wp[1].w_float; + d = wp[2].w_float; + cminusb = c-b; + outlet_float(x->x_obj.ob_outlet, b + frac * ( + cminusb - 0.1666667f * (1.-frac) * ( + (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b)))); + } +} + +static void tabread4_set(t_tabread4 *x, t_symbol *s) +{ + x->x_arrayname = s; +} + +static void *tabread4_new(t_symbol *s) +{ + t_tabread4 *x = (t_tabread4 *)pd_new(tabread4_class); + x->x_arrayname = s; + outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void tabread4_setup(void) +{ + tabread4_class = class_new(gensym("tabread4"), (t_newmethod)tabread4_new, + 0, sizeof(t_tabread4), 0, A_DEFSYM, 0); + class_addfloat(tabread4_class, (t_method)tabread4_float); + class_addmethod(tabread4_class, (t_method)tabread4_set, gensym("set"), + A_SYMBOL, 0); +} + +/* ------------------ tabwrite: control ------------------------ */ + +static t_class *tabwrite_class; + +typedef struct _tabwrite +{ + t_object x_obj; + t_symbol *x_arrayname; + t_float x_ft1; +} t_tabwrite; + +static void tabwrite_float(t_tabwrite *x, t_float f) +{ + int i, vecsize; + t_garray *a; + t_word *vec; + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + pd_error(x, "%s: no such array", x->x_arrayname->s_name); + else if (!garray_getfloatwords(a, &vecsize, &vec)) + pd_error(x, "%s: bad template for tabwrite", x->x_arrayname->s_name); + else + { + int n = x->x_ft1; + if (n < 0) + n = 0; + else if (n >= vecsize) + n = vecsize-1; + vec[n].w_float = f; + garray_redraw(a); + } +} + +static void tabwrite_set(t_tabwrite *x, t_symbol *s) +{ + x->x_arrayname = s; +} + +static void *tabwrite_new(t_symbol *s) +{ + t_tabwrite *x = (t_tabwrite *)pd_new(tabwrite_class); + x->x_ft1 = 0; + x->x_arrayname = s; + floatinlet_new(&x->x_obj, &x->x_ft1); + return (x); +} + +void tabwrite_setup(void) +{ + tabwrite_class = class_new(gensym("tabwrite"), (t_newmethod)tabwrite_new, + 0, sizeof(t_tabwrite), 0, A_DEFSYM, 0); + class_addfloat(tabwrite_class, (t_method)tabwrite_float); + class_addmethod(tabwrite_class, (t_method)tabwrite_set, gensym("set"), + A_SYMBOL, 0); +} + +/* ------------------------ global setup routine ------------------------- */ + +void d_array_setup(void) +{ + tabwrite_tilde_setup(); + tabplay_tilde_setup(); + tabread_tilde_setup(); + tabread4_tilde_setup(); + tabosc4_tilde_setup(); + tabsend_setup(); + tabreceive_setup(); + tabread_setup(); + tabread4_setup(); + tabwrite_setup(); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/d_ctl.c b/ports/camomile/source/LibPd/pure-data/src/d_ctl.c new file mode 100644 index 00000000..e98b15b4 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_ctl.c @@ -0,0 +1,850 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* sig~ and line~ control-to-signal converters; + snapshot~ signal-to-control converter. +*/ + +#include "m_pd.h" +#include "math.h" + +/* -------------------------- sig~ ------------------------------ */ +static t_class *sig_tilde_class; + +typedef struct _sig +{ + t_object x_obj; + t_float x_f; +} t_sig; + +static t_int *sig_tilde_perform(t_int *w) +{ + t_float f = *(t_float *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)(w[3]); + while (n--) + *out++ = f; + return (w+4); +} + +static t_int *sig_tilde_perf8(t_int *w) +{ + t_float f = *(t_float *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)(w[3]); + + for (; n; n -= 8, out += 8) + { + out[0] = f; + out[1] = f; + out[2] = f; + out[3] = f; + out[4] = f; + out[5] = f; + out[6] = f; + out[7] = f; + } + return (w+4); +} + +void dsp_add_scalarcopy(t_float *in, t_sample *out, int n) +{ + if (n&7) + dsp_add(sig_tilde_perform, 3, in, out, n); + else + dsp_add(sig_tilde_perf8, 3, in, out, n); +} + +static void sig_tilde_float(t_sig *x, t_float f) +{ + x->x_f = f; +} + +static void sig_tilde_dsp(t_sig *x, t_signal **sp) +{ + dsp_add(sig_tilde_perform, 3, &x->x_f, sp[0]->s_vec, sp[0]->s_n); +} + +static void *sig_tilde_new(t_floatarg f) +{ + t_sig *x = (t_sig *)pd_new(sig_tilde_class); + x->x_f = f; + outlet_new(&x->x_obj, gensym("signal")); + return (x); +} + +static void sig_tilde_setup(void) +{ + sig_tilde_class = class_new(gensym("sig~"), (t_newmethod)sig_tilde_new, 0, + sizeof(t_sig), 0, A_DEFFLOAT, 0); + class_addfloat(sig_tilde_class, (t_method)sig_tilde_float); + class_addmethod(sig_tilde_class, (t_method)sig_tilde_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* -------------------------- line~ ------------------------------ */ +static t_class *line_tilde_class; + +typedef struct _line +{ + t_object x_obj; + t_sample x_target; /* target value of ramp */ + t_sample x_value; /* current value of ramp at block-borders */ + t_sample x_biginc; + t_sample x_inc; + t_float x_1overn; + t_float x_dspticktomsec; + t_float x_inletvalue; + t_float x_inletwas; + int x_ticksleft; + int x_retarget; +} t_line; + +static t_int *line_tilde_perform(t_int *w) +{ + t_line *x = (t_line *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)(w[3]); + t_sample f = x->x_value; + + if (PD_BIGORSMALL(f)) + x->x_value = f = 0; + if (x->x_retarget) + { + int nticks = x->x_inletwas * x->x_dspticktomsec; + if (!nticks) nticks = 1; + x->x_ticksleft = nticks; + x->x_biginc = (x->x_target - x->x_value)/(t_float)nticks; + x->x_inc = x->x_1overn * x->x_biginc; + x->x_retarget = 0; + } + if (x->x_ticksleft) + { + t_sample f = x->x_value; + while (n--) *out++ = f, f += x->x_inc; + x->x_value += x->x_biginc; + x->x_ticksleft--; + } + else + { + t_sample g = x->x_value = x->x_target; + while (n--) + *out++ = g; + } + return (w+4); +} + +/* TB: vectorized version */ +static t_int *line_tilde_perf8(t_int *w) +{ + t_line *x = (t_line *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)(w[3]); + t_sample f = x->x_value; + + if (PD_BIGORSMALL(f)) + x->x_value = f = 0; + if (x->x_retarget) + { + int nticks = x->x_inletwas * x->x_dspticktomsec; + if (!nticks) nticks = 1; + x->x_ticksleft = nticks; + x->x_biginc = (x->x_target - x->x_value)/(t_sample)nticks; + x->x_inc = x->x_1overn * x->x_biginc; + x->x_retarget = 0; + } + if (x->x_ticksleft) + { + t_sample f = x->x_value; + while (n--) *out++ = f, f += x->x_inc; + x->x_value += x->x_biginc; + x->x_ticksleft--; + } + else + { + t_sample f = x->x_value = x->x_target; + for (; n; n -= 8, out += 8) + { + out[0] = f; out[1] = f; out[2] = f; out[3] = f; + out[4] = f; out[5] = f; out[6] = f; out[7] = f; + } + } + return (w+4); +} + +static void line_tilde_float(t_line *x, t_float f) +{ + if (x->x_inletvalue <= 0) + { + x->x_target = x->x_value = f; + x->x_ticksleft = x->x_retarget = 0; + } + else + { + x->x_target = f; + x->x_retarget = 1; + x->x_inletwas = x->x_inletvalue; + x->x_inletvalue = 0; + } +} + +static void line_tilde_stop(t_line *x) +{ + x->x_target = x->x_value; + x->x_ticksleft = x->x_retarget = 0; +} + +static void line_tilde_dsp(t_line *x, t_signal **sp) +{ + if(sp[0]->s_n&7) + dsp_add(line_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); + else + dsp_add(line_tilde_perf8, 3, x, sp[0]->s_vec, sp[0]->s_n); + x->x_1overn = 1./sp[0]->s_n; + x->x_dspticktomsec = sp[0]->s_sr / (1000 * sp[0]->s_n); +} + +static void *line_tilde_new(void) +{ + t_line *x = (t_line *)pd_new(line_tilde_class); + outlet_new(&x->x_obj, gensym("signal")); + floatinlet_new(&x->x_obj, &x->x_inletvalue); + x->x_ticksleft = x->x_retarget = 0; + x->x_value = x->x_target = x->x_inletvalue = x->x_inletwas = 0; + return (x); +} + +static void line_tilde_setup(void) +{ + line_tilde_class = class_new(gensym("line~"), line_tilde_new, 0, + sizeof(t_line), 0, 0); + class_addfloat(line_tilde_class, (t_method)line_tilde_float); + class_addmethod(line_tilde_class, (t_method)line_tilde_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(line_tilde_class, (t_method)line_tilde_stop, + gensym("stop"), 0); +} + +/* -------------------------- vline~ ------------------------------ */ +static t_class *vline_tilde_class; +#include "s_stuff.h" /* for DEFDACBLKSIZE; this should be in m_pd.h */ +typedef struct _vseg +{ + double s_targettime; + double s_starttime; + t_sample s_target; + struct _vseg *s_next; +} t_vseg; + +typedef struct _vline +{ + t_object x_obj; + double x_value; + double x_inc; + double x_referencetime; + double x_lastlogicaltime; + double x_nextblocktime; + double x_samppermsec; + double x_msecpersamp; + double x_targettime; + t_sample x_target; + t_float x_inlet1; + t_float x_inlet2; + t_vseg *x_list; +} t_vline; + +static t_int *vline_tilde_perform(t_int *w) +{ + t_vline *x = (t_vline *)(w[1]); + t_float *out = (t_float *)(w[2]); + int n = (int)(w[3]), i; + double f = x->x_value; + double inc = x->x_inc; + double msecpersamp = x->x_msecpersamp; + double samppermsec = x->x_samppermsec; + double timenow, logicaltimenow = clock_gettimesince(x->x_referencetime); + t_vseg *s = x->x_list; + if (logicaltimenow != x->x_lastlogicaltime) + { + int sampstotime = (n > DEFDACBLKSIZE ? n : DEFDACBLKSIZE); + x->x_lastlogicaltime = logicaltimenow; + x->x_nextblocktime = logicaltimenow - sampstotime * msecpersamp; + } + timenow = x->x_nextblocktime; + x->x_nextblocktime = timenow + n * msecpersamp; + for (i = 0; i < n; i++) + { + double timenext = timenow + msecpersamp; + checknext: + if (s) + { + /* has starttime elapsed? If so update value and increment */ + if (s->s_starttime < timenext) + { + if (x->x_targettime <= timenext) + f = x->x_target, inc = 0; + /* if zero-length segment bash output value */ + if (s->s_targettime <= s->s_starttime) + { + f = s->s_target; + inc = 0; + } + else + { + double incpermsec = (s->s_target - f)/ + (s->s_targettime - s->s_starttime); + f = f + incpermsec * (timenext - s->s_starttime); + inc = incpermsec * msecpersamp; + } + x->x_inc = inc; + x->x_target = s->s_target; + x->x_targettime = s->s_targettime; + x->x_list = s->s_next; + t_freebytes(s, sizeof(*s)); + s = x->x_list; + goto checknext; + } + } + if (x->x_targettime <= timenext) + f = x->x_target, inc = x->x_inc = 0, x->x_targettime = 1e20; + *out++ = f; + f = f + inc; + timenow = timenext; + } + x->x_value = f; + return (w+4); +} + +static void vline_tilde_stop(t_vline *x) +{ + t_vseg *s1, *s2; + for (s1 = x->x_list; s1; s1 = s2) + s2 = s1->s_next, t_freebytes(s1, sizeof(*s1)); + x->x_list = 0; + x->x_inc = 0; + x->x_inlet1 = x->x_inlet2 = 0; + x->x_target = x->x_value; + x->x_targettime = 1e20; +} + +static void vline_tilde_float(t_vline *x, t_float f) +{ + double timenow = clock_gettimesince(x->x_referencetime); + t_float inlet1 = (x->x_inlet1 < 0 ? 0 : x->x_inlet1); + t_float inlet2 = x->x_inlet2; + double starttime = timenow + inlet2; + t_vseg *s1, *s2, *deletefrom = 0, *snew; + if (PD_BIGORSMALL(f)) + f = 0; + + /* negative delay input means stop and jump immediately to new value */ + if (inlet2 < 0) + { + x->x_value = f; + vline_tilde_stop(x); + return; + } + snew = (t_vseg *)t_getbytes(sizeof(*snew)); + /* check if we supplant the first item in the list. We supplant + an item by having an earlier starttime, or an equal starttime unless + the equal one was instantaneous and the new one isn't (in which case + we'll do a jump-and-slide starting at that time.) */ + if (!x->x_list || x->x_list->s_starttime > starttime || + (x->x_list->s_starttime == starttime && + (x->x_list->s_targettime > x->x_list->s_starttime || inlet1 <= 0))) + { + deletefrom = x->x_list; + x->x_list = snew; + } + else + { + for (s1 = x->x_list; (s2 = s1->s_next); s1 = s2) + { + if (s2->s_starttime > starttime || + (s2->s_starttime == starttime && + (s2->s_targettime > s2->s_starttime || inlet1 <= 0))) + { + deletefrom = s2; + s1->s_next = snew; + goto didit; + } + } + s1->s_next = snew; + deletefrom = 0; + didit: ; + } + while (deletefrom) + { + s1 = deletefrom->s_next; + t_freebytes(deletefrom, sizeof(*deletefrom)); + deletefrom = s1; + } + snew->s_next = 0; + snew->s_target = f; + snew->s_starttime = starttime; + snew->s_targettime = starttime + inlet1; + x->x_inlet1 = x->x_inlet2 = 0; +} + +static void vline_tilde_dsp(t_vline *x, t_signal **sp) +{ + dsp_add(vline_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); + x->x_samppermsec = ((double)(sp[0]->s_sr)) / 1000; + x->x_msecpersamp = ((double)1000) / sp[0]->s_sr; +} + +static void *vline_tilde_new(void) +{ + t_vline *x = (t_vline *)pd_new(vline_tilde_class); + outlet_new(&x->x_obj, gensym("signal")); + floatinlet_new(&x->x_obj, &x->x_inlet1); + floatinlet_new(&x->x_obj, &x->x_inlet2); + x->x_inlet1 = x->x_inlet2 = 0; + x->x_value = x->x_inc = 0; + x->x_referencetime = x->x_lastlogicaltime = x->x_nextblocktime = + clock_getlogicaltime(); + x->x_list = 0; + x->x_samppermsec = 0; + x->x_targettime = 1e20; + return (x); +} + +static void vline_tilde_setup(void) +{ + vline_tilde_class = class_new(gensym("vline~"), vline_tilde_new, + (t_method)vline_tilde_stop, sizeof(t_vline), 0, 0); + class_addfloat(vline_tilde_class, (t_method)vline_tilde_float); + class_addmethod(vline_tilde_class, (t_method)vline_tilde_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(vline_tilde_class, (t_method)vline_tilde_stop, + gensym("stop"), 0); +} + +/* -------------------------- snapshot~ ------------------------------ */ +static t_class *snapshot_tilde_class; + +typedef struct _snapshot +{ + t_object x_obj; + t_sample x_value; + t_float x_f; +} t_snapshot; + +static void *snapshot_tilde_new(void) +{ + t_snapshot *x = (t_snapshot *)pd_new(snapshot_tilde_class); + x->x_value = 0; + outlet_new(&x->x_obj, &s_float); + x->x_f = 0; + return (x); +} + +static t_int *snapshot_tilde_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + *out = *in; + return (w+3); +} + +static void snapshot_tilde_dsp(t_snapshot *x, t_signal **sp) +{ + dsp_add(snapshot_tilde_perform, 2, sp[0]->s_vec + (sp[0]->s_n-1), + &x->x_value); +} + +static void snapshot_tilde_bang(t_snapshot *x) +{ + outlet_float(x->x_obj.ob_outlet, x->x_value); +} + +static void snapshot_tilde_set(t_snapshot *x, t_floatarg f) +{ + x->x_value = f; +} + +static void snapshot_tilde_setup(void) +{ + snapshot_tilde_class = class_new(gensym("snapshot~"), snapshot_tilde_new, 0, + sizeof(t_snapshot), 0, 0); + CLASS_MAINSIGNALIN(snapshot_tilde_class, t_snapshot, x_f); + class_addmethod(snapshot_tilde_class, (t_method)snapshot_tilde_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(snapshot_tilde_class, (t_method)snapshot_tilde_set, + gensym("set"), A_DEFFLOAT, 0); + class_addbang(snapshot_tilde_class, snapshot_tilde_bang); +} + +/* -------------------------- vsnapshot~ ------------------------------ */ +static t_class *vsnapshot_tilde_class; + +typedef struct _vsnapshot +{ + t_object x_obj; + int x_n; + int x_gotone; + t_sample *x_vec; + t_float x_f; + t_float x_sampspermsec; + double x_time; +} t_vsnapshot; + +static void *vsnapshot_tilde_new(void) +{ + t_vsnapshot *x = (t_vsnapshot *)pd_new(vsnapshot_tilde_class); + outlet_new(&x->x_obj, &s_float); + x->x_f = 0; + x->x_n = 0; + x->x_vec = 0; + x->x_gotone = 0; + return (x); +} + +static t_int *vsnapshot_tilde_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_vsnapshot *x = (t_vsnapshot *)(w[2]); + t_sample *out = x->x_vec; + int n = x->x_n, i; + for (i = 0; i < n; i++) + out[i] = in[i]; + x->x_time = clock_getlogicaltime(); + x->x_gotone = 1; + return (w+3); +} + +static void vsnapshot_tilde_dsp(t_vsnapshot *x, t_signal **sp) +{ + int n = sp[0]->s_n; + if (n != x->x_n) + { + if (x->x_vec) + t_freebytes(x->x_vec, x->x_n * sizeof(t_sample)); + x->x_vec = (t_sample *)getbytes(n * sizeof(t_sample)); + x->x_gotone = 0; + x->x_n = n; + } + x->x_sampspermsec = sp[0]->s_sr / 1000; + dsp_add(vsnapshot_tilde_perform, 2, sp[0]->s_vec, x); +} + +static void vsnapshot_tilde_bang(t_vsnapshot *x) +{ + t_sample val; + if (x->x_gotone) + { + int indx = clock_gettimesince(x->x_time) * x->x_sampspermsec; + if (indx < 0) + indx = 0; + else if (indx >= x->x_n) + indx = x->x_n - 1; + val = x->x_vec[indx]; + } + else val = 0; + outlet_float(x->x_obj.ob_outlet, val); +} + +static void vsnapshot_tilde_ff(t_vsnapshot *x) +{ + if (x->x_vec) + t_freebytes(x->x_vec, x->x_n * sizeof(t_sample)); +} + +static void vsnapshot_tilde_setup(void) +{ + vsnapshot_tilde_class = class_new(gensym("vsnapshot~"), + vsnapshot_tilde_new, (t_method)vsnapshot_tilde_ff, + sizeof(t_vsnapshot), 0, 0); + CLASS_MAINSIGNALIN(vsnapshot_tilde_class, t_vsnapshot, x_f); + class_addmethod(vsnapshot_tilde_class, (t_method)vsnapshot_tilde_dsp, + gensym("dsp"), A_CANT, 0); + class_addbang(vsnapshot_tilde_class, vsnapshot_tilde_bang); +} + + +/* ---------------- env~ - simple envelope follower. ----------------- */ + +#define MAXOVERLAP 32 +#define INITVSTAKEN 64 + +typedef struct sigenv +{ + t_object x_obj; /* header */ + void *x_outlet; /* a "float" outlet */ + void *x_clock; /* a "clock" object */ + t_sample *x_buf; /* a Hanning window */ + int x_phase; /* number of points since last output */ + int x_period; /* requested period of output */ + int x_realperiod; /* period rounded up to vecsize multiple */ + int x_npoints; /* analysis window size in samples */ + t_float x_result; /* result to output */ + t_sample x_sumbuf[MAXOVERLAP]; /* summing buffer */ + t_float x_f; + int x_allocforvs; /* extra buffer for DSP vector size */ +} t_sigenv; + +t_class *env_tilde_class; +static void env_tilde_tick(t_sigenv *x); + +static void *env_tilde_new(t_floatarg fnpoints, t_floatarg fperiod) +{ + int npoints = fnpoints; + int period = fperiod; + t_sigenv *x; + t_sample *buf; + int i; + + if (npoints < 1) npoints = 1024; + if (period < 1) period = npoints/2; + if (period < npoints / MAXOVERLAP + 1) + period = npoints / MAXOVERLAP + 1; + if (!(buf = getbytes(sizeof(t_sample) * (npoints + INITVSTAKEN)))) + { + error("env: couldn't allocate buffer"); + return (0); + } + x = (t_sigenv *)pd_new(env_tilde_class); + x->x_buf = buf; + x->x_npoints = npoints; + x->x_phase = 0; + x->x_period = period; + for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0; + for (i = 0; i < npoints; i++) + buf[i] = (1. - cos((2 * 3.14159 * i) / npoints))/npoints; + for (; i < npoints+INITVSTAKEN; i++) buf[i] = 0; + x->x_clock = clock_new(x, (t_method)env_tilde_tick); + x->x_outlet = outlet_new(&x->x_obj, gensym("float")); + x->x_f = 0; + x->x_allocforvs = INITVSTAKEN; + return (x); +} + +static t_int *env_tilde_perform(t_int *w) +{ + t_sigenv *x = (t_sigenv *)(w[1]); + t_sample *in = (t_sample *)(w[2]); + int n = (int)(w[3]); + int count; + t_sample *sump; + in += n; + for (count = x->x_phase, sump = x->x_sumbuf; + count < x->x_npoints; count += x->x_realperiod, sump++) + { + t_sample *hp = x->x_buf + count; + t_sample *fp = in; + t_sample sum = *sump; + int i; + + for (i = 0; i < n; i++) + { + fp--; + sum += *hp++ * (*fp * *fp); + } + *sump = sum; + } + sump[0] = 0; + x->x_phase -= n; + if (x->x_phase < 0) + { + x->x_result = x->x_sumbuf[0]; + for (count = x->x_realperiod, sump = x->x_sumbuf; + count < x->x_npoints; count += x->x_realperiod, sump++) + sump[0] = sump[1]; + sump[0] = 0; + x->x_phase = x->x_realperiod - n; + clock_delay(x->x_clock, 0L); + } + return (w+4); +} + +static void env_tilde_dsp(t_sigenv *x, t_signal **sp) +{ + if (x->x_period % sp[0]->s_n) x->x_realperiod = + x->x_period + sp[0]->s_n - (x->x_period % sp[0]->s_n); + else x->x_realperiod = x->x_period; + if (sp[0]->s_n > x->x_allocforvs) + { + void *xx = resizebytes(x->x_buf, + (x->x_npoints + x->x_allocforvs) * sizeof(t_sample), + (x->x_npoints + sp[0]->s_n) * sizeof(t_sample)); + if (!xx) + { + error("env~: out of memory"); + return; + } + x->x_buf = (t_sample *)xx; + x->x_allocforvs = sp[0]->s_n; + } + dsp_add(env_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); +} + +static void env_tilde_tick(t_sigenv *x) /* callback function for the clock */ +{ + outlet_float(x->x_outlet, powtodb(x->x_result)); +} + +static void env_tilde_ff(t_sigenv *x) /* cleanup on free */ +{ + clock_free(x->x_clock); + freebytes(x->x_buf, (x->x_npoints + x->x_allocforvs) * sizeof(*x->x_buf)); +} + + +void env_tilde_setup(void ) +{ + env_tilde_class = class_new(gensym("env~"), (t_newmethod)env_tilde_new, + (t_method)env_tilde_ff, sizeof(t_sigenv), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(env_tilde_class, t_sigenv, x_f); + class_addmethod(env_tilde_class, (t_method)env_tilde_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* --------------------- threshold~ ----------------------------- */ + +static t_class *threshold_tilde_class; + +typedef struct _threshold_tilde +{ + t_object x_obj; + t_outlet *x_outlet1; /* bang out for high thresh */ + t_outlet *x_outlet2; /* bang out for low thresh */ + t_clock *x_clock; /* wakeup for message output */ + t_float x_f; /* scalar inlet */ + int x_state; /* 1 = high, 0 = low */ + t_float x_hithresh; /* value of high threshold */ + t_float x_lothresh; /* value of low threshold */ + t_float x_deadwait; /* msec remaining in dead period */ + t_float x_msecpertick; /* msec per DSP tick */ + t_float x_hideadtime; /* hi dead time in msec */ + t_float x_lodeadtime; /* lo dead time in msec */ +} t_threshold_tilde; + +static void threshold_tilde_tick(t_threshold_tilde *x); +static void threshold_tilde_set(t_threshold_tilde *x, + t_floatarg hithresh, t_floatarg hideadtime, + t_floatarg lothresh, t_floatarg lodeadtime); + +static t_threshold_tilde *threshold_tilde_new(t_floatarg hithresh, + t_floatarg hideadtime, t_floatarg lothresh, t_floatarg lodeadtime) +{ + t_threshold_tilde *x = (t_threshold_tilde *) + pd_new(threshold_tilde_class); + x->x_state = 0; /* low state */ + x->x_deadwait = 0; /* no dead time */ + x->x_clock = clock_new(x, (t_method)threshold_tilde_tick); + x->x_outlet1 = outlet_new(&x->x_obj, &s_bang); + x->x_outlet2 = outlet_new(&x->x_obj, &s_bang); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1")); + x->x_msecpertick = 0.; + x->x_f = 0; + threshold_tilde_set(x, hithresh, hideadtime, lothresh, lodeadtime); + return (x); +} + + /* "set" message to specify thresholds and dead times */ +static void threshold_tilde_set(t_threshold_tilde *x, + t_floatarg hithresh, t_floatarg hideadtime, + t_floatarg lothresh, t_floatarg lodeadtime) +{ + if (lothresh > hithresh) + lothresh = hithresh; + x->x_hithresh = hithresh; + x->x_hideadtime = hideadtime; + x->x_lothresh = lothresh; + x->x_lodeadtime = lodeadtime; +} + + /* number in inlet sets state -- note incompatible with JMAX which used + "int" message for this, impossible here because of auto signal conversion */ +static void threshold_tilde_ft1(t_threshold_tilde *x, t_floatarg f) +{ + x->x_state = (f != 0); + x->x_deadwait = 0; +} + +static void threshold_tilde_tick(t_threshold_tilde *x) +{ + if (x->x_state) + outlet_bang(x->x_outlet1); + else outlet_bang(x->x_outlet2); +} + +static t_int *threshold_tilde_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_threshold_tilde *x = (t_threshold_tilde *)(w[2]); + int n = (int)w[3]; + if (x->x_deadwait > 0) + x->x_deadwait -= x->x_msecpertick; + else if (x->x_state) + { + /* we're high; look for low sample */ + for (; n--; in1++) + { + if (*in1 < x->x_lothresh) + { + clock_delay(x->x_clock, 0L); + x->x_state = 0; + x->x_deadwait = x->x_lodeadtime; + goto done; + } + } + } + else + { + /* we're low; look for high sample */ + for (; n--; in1++) + { + if (*in1 >= x->x_hithresh) + { + clock_delay(x->x_clock, 0L); + x->x_state = 1; + x->x_deadwait = x->x_hideadtime; + goto done; + } + } + } +done: + return (w+4); +} + +void threshold_tilde_dsp(t_threshold_tilde *x, t_signal **sp) +{ + x->x_msecpertick = 1000. * sp[0]->s_n / sp[0]->s_sr; + dsp_add(threshold_tilde_perform, 3, sp[0]->s_vec, x, sp[0]->s_n); +} + +static void threshold_tilde_ff(t_threshold_tilde *x) +{ + clock_free(x->x_clock); +} + +static void threshold_tilde_setup( void) +{ + threshold_tilde_class = class_new(gensym("threshold~"), + (t_newmethod)threshold_tilde_new, (t_method)threshold_tilde_ff, + sizeof(t_threshold_tilde), 0, + A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(threshold_tilde_class, t_threshold_tilde, x_f); + class_addmethod(threshold_tilde_class, (t_method)threshold_tilde_set, + gensym("set"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(threshold_tilde_class, (t_method)threshold_tilde_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(threshold_tilde_class, (t_method)threshold_tilde_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ------------------------ global setup routine ------------------------- */ + +void d_ctl_setup(void) +{ + sig_tilde_setup(); + line_tilde_setup(); + vline_tilde_setup(); + snapshot_tilde_setup(); + vsnapshot_tilde_setup(); + env_tilde_setup(); + threshold_tilde_setup(); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/d_dac.c b/ports/camomile/source/LibPd/pure-data/src/d_dac.c new file mode 100644 index 00000000..9f9bb897 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_dac.c @@ -0,0 +1,202 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* The dac~ and adc~ routines. +*/ + +#include "m_pd.h" +#include "s_stuff.h" + +/* ----------------------------- dac~ --------------------------- */ +static t_class *dac_class; + +typedef struct _dac +{ + t_object x_obj; + t_int x_n; + t_int *x_vec; + t_float x_f; +} t_dac; + +static void *dac_new(t_symbol *s, int argc, t_atom *argv) +{ + t_dac *x = (t_dac *)pd_new(dac_class); + t_atom defarg[2], *ap; + int i; + if (!argc) + { + argv = defarg; + argc = 2; + SETFLOAT(&defarg[0], 1); + SETFLOAT(&defarg[1], 2); + } + x->x_n = argc; + x->x_vec = (t_int *)getbytes(argc * sizeof(*x->x_vec)); + for (i = 0; i < argc; i++) + x->x_vec[i] = atom_getfloatarg(i, argc, argv); + for (i = 1; i < argc; i++) + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + x->x_f = 0; + return (x); +} + +static void dac_dsp(t_dac *x, t_signal **sp) +{ + t_int i, *ip; + t_signal **sp2; + for (i = x->x_n, ip = x->x_vec, sp2 = sp; i--; ip++, sp2++) + { + int ch = (int)(*ip - 1); + if ((*sp2)->s_n != DEFDACBLKSIZE) + error("dac~: bad vector size"); + else if (ch >= 0 && ch < sys_get_outchannels()) + dsp_add(plus_perform, 4, STUFF->st_soundout + DEFDACBLKSIZE*ch, + (*sp2)->s_vec, STUFF->st_soundout + DEFDACBLKSIZE*ch, DEFDACBLKSIZE); + } +} + +static void dac_set(t_dac *x, t_symbol *s, int argc, t_atom *argv) +{ + int i; + for (i = 0; i < argc && i < x->x_n; i++) + x->x_vec[i] = atom_getfloatarg(i, argc, argv); + canvas_update_dsp(); +} + +static void dac_free(t_dac *x) +{ + freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec)); +} + +static void dac_setup(void) +{ + dac_class = class_new(gensym("dac~"), (t_newmethod)dac_new, + (t_method)dac_free, sizeof(t_dac), 0, A_GIMME, 0); + CLASS_MAINSIGNALIN(dac_class, t_dac, x_f); + class_addmethod(dac_class, (t_method)dac_dsp, gensym("dsp"), A_CANT, 0); + class_addmethod(dac_class, (t_method)dac_set, gensym("set"), A_GIMME, 0); + class_sethelpsymbol(dac_class, gensym("adc~_dac~")); +} + +/* ----------------------------- adc~ --------------------------- */ +static t_class *adc_class; + +typedef struct _adc +{ + t_object x_obj; + t_int x_n; + t_int *x_vec; +} t_adc; + +static void *adc_new(t_symbol *s, int argc, t_atom *argv) +{ + t_adc *x = (t_adc *)pd_new(adc_class); + t_atom defarg[2], *ap; + int i; + if (!argc) + { + argv = defarg; + argc = 2; + SETFLOAT(&defarg[0], 1); + SETFLOAT(&defarg[1], 2); + } + x->x_n = argc; + x->x_vec = (t_int *)getbytes(argc * sizeof(*x->x_vec)); + for (i = 0; i < argc; i++) + x->x_vec[i] = atom_getfloatarg(i, argc, argv); + for (i = 0; i < argc; i++) + outlet_new(&x->x_obj, &s_signal); + return (x); +} + +t_int *copy_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)(w[3]); + while (n--) *out++ = *in1++; + return (w+4); +} + +static t_int *copy_perf8(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)(w[3]); + + for (; n; n -= 8, in1 += 8, out += 8) + { + t_sample f0 = in1[0]; + t_sample f1 = in1[1]; + t_sample f2 = in1[2]; + t_sample f3 = in1[3]; + t_sample f4 = in1[4]; + t_sample f5 = in1[5]; + t_sample f6 = in1[6]; + t_sample f7 = in1[7]; + + out[0] = f0; + out[1] = f1; + out[2] = f2; + out[3] = f3; + out[4] = f4; + out[5] = f5; + out[6] = f6; + out[7] = f7; + } + return (w+4); +} + +void dsp_add_copy(t_sample *in, t_sample *out, int n) +{ + if (n&7) + dsp_add(copy_perform, 3, in, out, n); + else + dsp_add(copy_perf8, 3, in, out, n); +} + +static void adc_dsp(t_adc *x, t_signal **sp) +{ + t_int i, *ip; + t_signal **sp2; + for (i = x->x_n, ip = x->x_vec, sp2 = sp; i--; ip++, sp2++) + { + int ch = (int)(*ip - 1); + if ((*sp2)->s_n != DEFDACBLKSIZE) + error("adc~: bad vector size"); + else if (ch >= 0 && ch < sys_get_inchannels()) + dsp_add_copy(STUFF->st_soundin + DEFDACBLKSIZE*ch, + (*sp2)->s_vec, DEFDACBLKSIZE); + else dsp_add_zero((*sp2)->s_vec, DEFDACBLKSIZE); + } +} + +static void adc_set(t_adc *x, t_symbol *s, int argc, t_atom *argv) +{ + int i; + for (i = 0; i < argc && i < x->x_n; i++) + x->x_vec[i] = atom_getfloatarg(i, argc, argv); + canvas_update_dsp(); +} + +static void adc_free(t_adc *x) +{ + freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec)); +} + +static void adc_setup(void) +{ + adc_class = class_new(gensym("adc~"), (t_newmethod)adc_new, + (t_method)adc_free, sizeof(t_adc), 0, A_GIMME, 0); + class_addmethod(adc_class, (t_method)adc_dsp, gensym("dsp"), A_CANT, 0); + class_addmethod(adc_class, (t_method)adc_set, gensym("set"), A_GIMME, 0); + class_sethelpsymbol(adc_class, gensym("adc~_dac~")); +} + +void d_dac_setup(void) +{ + dac_setup(); + adc_setup(); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/d_delay.c b/ports/camomile/source/LibPd/pure-data/src/d_delay.c new file mode 100644 index 00000000..87146b6d --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_delay.c @@ -0,0 +1,346 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* send~, delread~, throw~, catch~ */ + +#include "m_pd.h" +#include +extern int ugen_getsortno(void); + +#define DEFDELVS 64 /* LATER get this from canvas at DSP time */ +static const int delread_zero = 0; /* four bytes of zero for delread~, vd~*/ + +/* ----------------------------- delwrite~ ----------------------------- */ +static t_class *sigdelwrite_class; + +typedef struct delwritectl +{ + int c_n; + t_sample *c_vec; + int c_phase; +} t_delwritectl; + +typedef struct _sigdelwrite +{ + t_object x_obj; + t_symbol *x_sym; + t_float x_deltime; /* delay in msec (added by Mathieu Bouchard) */ + t_delwritectl x_cspace; + int x_sortno; /* DSP sort number at which this was last put on chain */ + int x_rsortno; /* DSP sort # for first delread or write in chain */ + int x_vecsize; /* vector size for delread~ to use */ + t_float x_f; +} t_sigdelwrite; + +#define XTRASAMPS 4 +#define SAMPBLK 4 + +static void sigdelwrite_updatesr(t_sigdelwrite *x, t_float sr) /* added by Mathieu Bouchard */ +{ + int nsamps = x->x_deltime * sr * (t_float)(0.001f); + if (nsamps < 1) nsamps = 1; + nsamps += ((- nsamps) & (SAMPBLK - 1)); + nsamps += DEFDELVS; + if (x->x_cspace.c_n != nsamps) + { + x->x_cspace.c_vec = (t_sample *)resizebytes(x->x_cspace.c_vec, + (x->x_cspace.c_n + XTRASAMPS) * sizeof(t_sample), + (nsamps + XTRASAMPS) * sizeof(t_sample)); + x->x_cspace.c_n = nsamps; + x->x_cspace.c_phase = XTRASAMPS; + } +} + +static void sigdelwrite_clear (t_sigdelwrite *x) /* added by Orm Finnendahl */ +{ + if (x->x_cspace.c_n > 0) + memset(x->x_cspace.c_vec, 0, sizeof(t_sample)*(x->x_cspace.c_n + XTRASAMPS)); +} + + + /* routine to check that all delwrites/delreads/vds have same vecsize */ +static void sigdelwrite_checkvecsize(t_sigdelwrite *x, int vecsize) +{ + if (x->x_rsortno != ugen_getsortno()) + { + x->x_vecsize = vecsize; + x->x_rsortno = ugen_getsortno(); + } + /* + LATER this should really check sample rate and blocking, once that is + supported. Probably we don't actually care about vecsize. + For now just suppress this check. */ +#if 0 + else if (vecsize != x->x_vecsize) + pd_error(x, "delread/delwrite/vd vector size mismatch"); +#endif +} + +static void *sigdelwrite_new(t_symbol *s, t_floatarg msec) +{ + t_sigdelwrite *x = (t_sigdelwrite *)pd_new(sigdelwrite_class); + if (!*s->s_name) s = gensym("delwrite~"); + pd_bind(&x->x_obj.ob_pd, s); + x->x_sym = s; + x->x_deltime = msec; + x->x_cspace.c_n = 0; + x->x_cspace.c_vec = getbytes(XTRASAMPS * sizeof(t_sample)); + x->x_sortno = 0; + x->x_vecsize = 0; + x->x_f = 0; + return (x); +} + +static t_int *sigdelwrite_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_delwritectl *c = (t_delwritectl *)(w[2]); + int n = (int)(w[3]); + int phase = c->c_phase, nsamps = c->c_n; + t_sample *vp = c->c_vec, *bp = vp + phase, *ep = vp + (c->c_n + XTRASAMPS); + phase += n; + + while (n--) + { + t_sample f = *in++; + if (PD_BIGORSMALL(f)) + f = 0; + *bp++ = f; + if (bp == ep) + { + vp[0] = ep[-4]; + vp[1] = ep[-3]; + vp[2] = ep[-2]; + vp[3] = ep[-1]; + bp = vp + XTRASAMPS; + phase -= nsamps; + } + } + c->c_phase = phase; + return (w+4); +} + +static void sigdelwrite_dsp(t_sigdelwrite *x, t_signal **sp) +{ + dsp_add(sigdelwrite_perform, 3, sp[0]->s_vec, &x->x_cspace, sp[0]->s_n); + x->x_sortno = ugen_getsortno(); + sigdelwrite_checkvecsize(x, sp[0]->s_n); + sigdelwrite_updatesr(x, sp[0]->s_sr); +} + +static void sigdelwrite_free(t_sigdelwrite *x) +{ + pd_unbind(&x->x_obj.ob_pd, x->x_sym); + freebytes(x->x_cspace.c_vec, + (x->x_cspace.c_n + XTRASAMPS) * sizeof(t_sample)); +} + +static void sigdelwrite_setup(void) +{ + sigdelwrite_class = class_new(gensym("delwrite~"), + (t_newmethod)sigdelwrite_new, (t_method)sigdelwrite_free, + sizeof(t_sigdelwrite), 0, A_DEFSYM, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(sigdelwrite_class, t_sigdelwrite, x_f); + class_addmethod(sigdelwrite_class, (t_method)sigdelwrite_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(sigdelwrite_class, (t_method)sigdelwrite_clear, + gensym("clear"), 0); +} + +/* ----------------------------- delread~ ----------------------------- */ +static t_class *sigdelread_class; + +typedef struct _sigdelread +{ + t_object x_obj; + t_symbol *x_sym; + t_float x_deltime; /* delay in msec */ + int x_delsamps; /* delay in samples */ + t_float x_sr; /* samples per msec */ + t_float x_n; /* vector size */ + int x_zerodel; /* 0 or vecsize depending on read/write order */ +} t_sigdelread; + +static void sigdelread_float(t_sigdelread *x, t_float f); + +static void *sigdelread_new(t_symbol *s, t_floatarg f) +{ + t_sigdelread *x = (t_sigdelread *)pd_new(sigdelread_class); + x->x_sym = s; + x->x_sr = 1; + x->x_n = 1; + x->x_zerodel = 0; + sigdelread_float(x, f); + outlet_new(&x->x_obj, &s_signal); + return (x); +} + +static void sigdelread_float(t_sigdelread *x, t_float f) +{ + int samps; + t_sigdelwrite *delwriter = + (t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class); + x->x_deltime = f; + if (delwriter) + { + int delsize = delwriter->x_cspace.c_n; + x->x_delsamps = (int)(0.5 + x->x_sr * x->x_deltime) + + x->x_n - x->x_zerodel; + if (x->x_delsamps < x->x_n) x->x_delsamps = x->x_n; + else if (x->x_delsamps > delwriter->x_cspace.c_n) + x->x_delsamps = delwriter->x_cspace.c_n; + } +} + +static t_int *sigdelread_perform(t_int *w) +{ + t_sample *out = (t_sample *)(w[1]); + t_delwritectl *c = (t_delwritectl *)(w[2]); + int delsamps = *(int *)(w[3]); + int n = (int)(w[4]); + int phase = c->c_phase - delsamps, nsamps = c->c_n; + t_sample *vp = c->c_vec, *bp, *ep = vp + (c->c_n + XTRASAMPS); + if (phase < 0) phase += nsamps; + bp = vp + phase; + + while (n--) + { + *out++ = *bp++; + if (bp == ep) bp -= nsamps; + } + return (w+5); +} + +static void sigdelread_dsp(t_sigdelread *x, t_signal **sp) +{ + t_sigdelwrite *delwriter = + (t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class); + x->x_sr = sp[0]->s_sr * 0.001; + x->x_n = sp[0]->s_n; + if (delwriter) + { + sigdelwrite_updatesr(delwriter, sp[0]->s_sr); + sigdelwrite_checkvecsize(delwriter, sp[0]->s_n); + x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ? + 0 : delwriter->x_vecsize); + sigdelread_float(x, x->x_deltime); + dsp_add(sigdelread_perform, 4, + sp[0]->s_vec, &delwriter->x_cspace, &x->x_delsamps, sp[0]->s_n); + } + else if (*x->x_sym->s_name) + error("delread~: %s: no such delwrite~",x->x_sym->s_name); +} + +static void sigdelread_setup(void) +{ + sigdelread_class = class_new(gensym("delread~"), + (t_newmethod)sigdelread_new, 0, + sizeof(t_sigdelread), 0, A_DEFSYM, A_DEFFLOAT, 0); + class_addmethod(sigdelread_class, (t_method)sigdelread_dsp, + gensym("dsp"), A_CANT, 0); + class_addfloat(sigdelread_class, (t_method)sigdelread_float); +} + + +/* ----------------------------- vd~ ----------------------------- */ +static t_class *sigvd_class; + +typedef struct _sigvd +{ + t_object x_obj; + t_symbol *x_sym; + t_float x_sr; /* samples per msec */ + int x_zerodel; /* 0 or vecsize depending on read/write order */ + t_float x_f; +} t_sigvd; + +static void *sigvd_new(t_symbol *s) +{ + t_sigvd *x = (t_sigvd *)pd_new(sigvd_class); + x->x_sym = s; + x->x_sr = 1; + x->x_zerodel = 0; + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); +} + +static t_int *sigvd_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + t_delwritectl *ctl = (t_delwritectl *)(w[3]); + t_sigvd *x = (t_sigvd *)(w[4]); + int n = (int)(w[5]); + + int nsamps = ctl->c_n; + t_sample limit = nsamps - n; + t_sample fn = n-1; + t_sample *vp = ctl->c_vec, *bp, *wp = vp + ctl->c_phase; + t_sample zerodel = x->x_zerodel; + while (n--) + { + t_sample delsamps = x->x_sr * *in++ - zerodel, frac; + int idelsamps; + t_sample a, b, c, d, cminusb; + if (!(delsamps >= 1.00001f)) /* too small or NAN */ + delsamps = 1.00001f; + if (delsamps > limit) /* too big */ + delsamps = limit; + delsamps += fn; + fn = fn - 1.0f; + idelsamps = delsamps; + frac = delsamps - (t_sample)idelsamps; + bp = wp - idelsamps; + if (bp < vp + 4) bp += nsamps; + d = bp[-3]; + c = bp[-2]; + b = bp[-1]; + a = bp[0]; + cminusb = c-b; + *out++ = b + frac * ( + cminusb - 0.1666667f * (1.-frac) * ( + (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b) + ) + ); + } + return (w+6); +} + +static void sigvd_dsp(t_sigvd *x, t_signal **sp) +{ + t_sigdelwrite *delwriter = + (t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class); + x->x_sr = sp[0]->s_sr * 0.001; + if (delwriter) + { + sigdelwrite_checkvecsize(delwriter, sp[0]->s_n); + x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ? + 0 : delwriter->x_vecsize); + dsp_add(sigvd_perform, 5, + sp[0]->s_vec, sp[1]->s_vec, + &delwriter->x_cspace, x, sp[0]->s_n); + } + else if (*x->x_sym->s_name) + error("vd~: %s: no such delwrite~",x->x_sym->s_name); +} + +static void sigvd_setup(void) +{ + sigvd_class = class_new(gensym("delread4~"), (t_newmethod)sigvd_new, 0, + sizeof(t_sigvd), 0, A_DEFSYM, 0); + class_addcreator((t_newmethod)sigvd_new, gensym("vd~"), A_DEFSYM, 0); + class_addmethod(sigvd_class, (t_method)sigvd_dsp, gensym("dsp"), A_CANT, 0); + CLASS_MAINSIGNALIN(sigvd_class, t_sigvd, x_f); +} + +/* ----------------------- global setup routine ---------------- */ + +void d_delay_setup(void) +{ + sigdelwrite_setup(); + sigdelread_setup(); + sigvd_setup(); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/d_fft.c b/ports/camomile/source/LibPd/pure-data/src/d_fft.c new file mode 100644 index 00000000..c53610bd --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_fft.c @@ -0,0 +1,355 @@ +/* Copyright (c) 1997- Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +/* This file interfaces to one of the Mayer, Ooura, or fftw FFT packages +to implement the "fft~", etc, Pd objects. If using Mayer, also compile +d_fft_mayer.c; if ooura, use d_fft_fftsg.c instead; if fftw, use d_fft_fftw.c +and also link in the fftw library. You can only have one of these three +linked in. The configure script can be used to select which one. +*/ + +/* ---------------- utility functions for DSP chains ---------------------- */ + + /* swap two arrays */ +static t_int *sigfft_swap(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + int n = (int)w[3]; + for (;n--; in1++, in2++) + { + t_sample f = *in1; + *in1 = *in2; + *in2 = f; + } + return (w+4); +} + + /* take array1 (supply a pointer to beginning) and copy it, + into decreasing addresses, into array 2 (supply a pointer one past the + end), and negate the sign. */ + +static t_int *sigrfft_flip(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)w[3]; + while (n--) + *(--out) = - *in++; + return (w+4); +} + +/* ------------------------ fft~ and ifft~ -------------------------------- */ +static t_class *sigfft_class, *sigifft_class; + +typedef struct fft +{ + t_object x_obj; + t_float x_f; +} t_sigfft; + +static void *sigfft_new(void) +{ + t_sigfft *x = (t_sigfft *)pd_new(sigfft_class); + outlet_new(&x->x_obj, gensym("signal")); + outlet_new(&x->x_obj, gensym("signal")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + x->x_f = 0; + return (x); +} + +static void *sigifft_new(void) +{ + t_sigfft *x = (t_sigfft *)pd_new(sigifft_class); + outlet_new(&x->x_obj, gensym("signal")); + outlet_new(&x->x_obj, gensym("signal")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + x->x_f = 0; + return (x); +} + +static t_int *sigfft_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + int n = (int)w[3]; + mayer_fft(n, in1, in2); + return (w+4); +} + +static t_int *sigifft_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + int n = (int)w[3]; + mayer_ifft(n, in1, in2); + return (w+4); +} + +static void sigfft_dspx(t_sigfft *x, t_signal **sp, t_int *(*f)(t_int *w)) +{ + int n = sp[0]->s_n; + t_sample *in1 = sp[0]->s_vec; + t_sample *in2 = sp[1]->s_vec; + t_sample *out1 = sp[2]->s_vec; + t_sample *out2 = sp[3]->s_vec; + if (out1 == in2 && out2 == in1) + dsp_add(sigfft_swap, 3, out1, out2, n); + else if (out1 == in2) + { + dsp_add(copy_perform, 3, in2, out2, n); + dsp_add(copy_perform, 3, in1, out1, n); + } + else + { + if (out1 != in1) dsp_add(copy_perform, 3, in1, out1, n); + if (out2 != in2) dsp_add(copy_perform, 3, in2, out2, n); + } + dsp_add(f, 3, sp[2]->s_vec, sp[3]->s_vec, n); +} + +static void sigfft_dsp(t_sigfft *x, t_signal **sp) +{ + sigfft_dspx(x, sp, sigfft_perform); +} + +static void sigifft_dsp(t_sigfft *x, t_signal **sp) +{ + sigfft_dspx(x, sp, sigifft_perform); +} + +static void sigfft_setup(void) +{ + sigfft_class = class_new(gensym("fft~"), sigfft_new, 0, + sizeof(t_sigfft), 0, 0); + CLASS_MAINSIGNALIN(sigfft_class, t_sigfft, x_f); + class_addmethod(sigfft_class, (t_method)sigfft_dsp, + gensym("dsp"), A_CANT, 0); + + sigifft_class = class_new(gensym("ifft~"), sigifft_new, 0, + sizeof(t_sigfft), 0, 0); + CLASS_MAINSIGNALIN(sigifft_class, t_sigfft, x_f); + class_addmethod(sigifft_class, (t_method)sigifft_dsp, + gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(sigifft_class, gensym("fft~")); +} + +/* ----------------------- rfft~ -------------------------------- */ + +static t_class *sigrfft_class; + +typedef struct rfft +{ + t_object x_obj; + t_float x_f; +} t_sigrfft; + +static void *sigrfft_new(void) +{ + t_sigrfft *x = (t_sigrfft *)pd_new(sigrfft_class); + outlet_new(&x->x_obj, gensym("signal")); + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *sigrfft_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + int n = (int)w[2]; + mayer_realfft(n, in); + return (w+3); +} + +static void sigrfft_dsp(t_sigrfft *x, t_signal **sp) +{ + int n = sp[0]->s_n, n2 = (n>>1); + t_sample *in1 = sp[0]->s_vec; + t_sample *out1 = sp[1]->s_vec; + t_sample *out2 = sp[2]->s_vec; + if (n < 4) + { + error("fft: minimum 4 points"); + return; + } + if (in1 != out1) + dsp_add(copy_perform, 3, in1, out1, n); + dsp_add(sigrfft_perform, 2, out1, n); + dsp_add(sigrfft_flip, 3, out1 + (n2+1), out2 + n2, n2-1); + dsp_add_zero(out1 + (n2+1), ((n2-1)&(~7))); + dsp_add_zero(out1 + (n2+1) + ((n2-1)&(~7)), ((n2-1)&7)); + dsp_add_zero(out2 + n2, n2); + dsp_add_zero(out2, 1); +} + +static void sigrfft_setup(void) +{ + sigrfft_class = class_new(gensym("rfft~"), sigrfft_new, 0, + sizeof(t_sigrfft), 0, 0); + CLASS_MAINSIGNALIN(sigrfft_class, t_sigrfft, x_f); + class_addmethod(sigrfft_class, (t_method)sigrfft_dsp, + gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(sigrfft_class, gensym("fft~")); +} + +/* ----------------------- rifft~ -------------------------------- */ + +static t_class *sigrifft_class; + +typedef struct rifft +{ + t_object x_obj; + t_float x_f; +} t_sigrifft; + +static void *sigrifft_new(void) +{ + t_sigrifft *x = (t_sigrifft *)pd_new(sigrifft_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *sigrifft_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + int n = (int)w[2]; + mayer_realifft(n, in); + return (w+3); +} + +static void sigrifft_dsp(t_sigrifft *x, t_signal **sp) +{ + int n = sp[0]->s_n, n2 = (n>>1); + t_sample *in1 = sp[0]->s_vec; + t_sample *in2 = sp[1]->s_vec; + t_sample *out1 = sp[2]->s_vec; + if (n < 4) + { + error("fft: minimum 4 points"); + return; + } + if (in2 == out1) + { + dsp_add(sigrfft_flip, 3, out1+1, out1 + n, n2-1); + dsp_add(copy_perform, 3, in1, out1, n2+1); + } + else + { + if (in1 != out1) dsp_add(copy_perform, 3, in1, out1, n2+1); + dsp_add(sigrfft_flip, 3, in2+1, out1 + n, n2-1); + } + dsp_add(sigrifft_perform, 2, out1, n); +} + +static void sigrifft_setup(void) +{ + sigrifft_class = class_new(gensym("rifft~"), sigrifft_new, 0, + sizeof(t_sigrifft), 0, 0); + CLASS_MAINSIGNALIN(sigrifft_class, t_sigrifft, x_f); + class_addmethod(sigrifft_class, (t_method)sigrifft_dsp, + gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(sigrifft_class, gensym("fft~")); +} + +/* ----------------------- framp~ -------------------------------- */ + +static t_class *sigframp_class; + +typedef struct framp +{ + t_object x_obj; + t_float x_f; +} t_sigframp; + +static void *sigframp_new(void) +{ + t_sigframp *x = (t_sigframp *)pd_new(sigframp_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + outlet_new(&x->x_obj, gensym("signal")); + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *sigframp_perform(t_int *w) +{ + t_sample *inreal = (t_sample *)(w[1]); + t_sample *inimag = (t_sample *)(w[2]); + t_sample *outfreq = (t_sample *)(w[3]); + t_sample *outamp = (t_sample *)(w[4]); + t_sample lastreal = 0, currentreal = inreal[0], nextreal = inreal[1]; + t_sample lastimag = 0, currentimag = inimag[0], nextimag = inimag[1]; + int n = (int)w[5]; + int m = n + 1; + t_sample fbin = 1, oneovern2 = 1.f/((t_sample)n * (t_sample)n); + + inreal += 2; + inimag += 2; + *outamp++ = *outfreq++ = 0; + n -= 2; + while (n--) + { + t_sample re, im, pow, freq; + lastreal = currentreal; + currentreal = nextreal; + nextreal = *inreal++; + lastimag = currentimag; + currentimag = nextimag; + nextimag = *inimag++; + re = currentreal - 0.5f * (lastreal + nextreal); + im = currentimag - 0.5f * (lastimag + nextimag); + pow = re * re + im * im; + if (pow > 1e-19) + { + t_sample detune = ((lastreal - nextreal) * re + + (lastimag - nextimag) * im) / (2.0f * pow); + if (detune > 2 || detune < -2) freq = pow = 0; + else freq = fbin + detune; + } + else freq = pow = 0; + *outfreq++ = freq; + *outamp++ = oneovern2 * pow; + fbin += 1.0f; + } + while (m--) *outamp++ = *outfreq++ = 0; + return (w+6); +} + +t_int *sigsqrt_perform(t_int *w); + +static void sigframp_dsp(t_sigframp *x, t_signal **sp) +{ + int n = sp[0]->s_n, n2 = (n>>1); + if (n < 4) + { + error("framp: minimum 4 points"); + return; + } + dsp_add(sigframp_perform, 5, sp[0]->s_vec, sp[1]->s_vec, + sp[2]->s_vec, sp[3]->s_vec, n2); + dsp_add(sigsqrt_perform, 3, sp[3]->s_vec, sp[3]->s_vec, n2); +} + +static void sigframp_setup(void) +{ + sigframp_class = class_new(gensym("framp~"), sigframp_new, 0, + sizeof(t_sigframp), 0, 0); + CLASS_MAINSIGNALIN(sigframp_class, t_sigframp, x_f); + class_addmethod(sigframp_class, (t_method)sigframp_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ------------------------ global setup routine ------------------------- */ + +void d_fft_setup(void) +{ + sigfft_setup(); + sigrfft_setup(); + sigrifft_setup(); + sigframp_setup(); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/d_fft_fftsg.c b/ports/camomile/source/LibPd/pure-data/src/d_fft_fftsg.c new file mode 100644 index 00000000..a8e11cdd --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_fft_fftsg.c @@ -0,0 +1,3486 @@ +/****************** begin Pd-specific prologue ***********************/ + +/* +This is the file, "fftsg.c" from the OOURA FFT package. The copyright notice +from Ooura's README is: + +Copyright: + Copyright(C) 1996-2001 Takuya OOURA + email: ooura@mmm.t.u-tokyo.ac.jp + download: http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html + You may use, copy, modify this code for any purpose and + without fee. You may distribute this ORIGINAL package. + +After the following prologue, the code is essentially Ooura's original, which I +believe the above notice permits me to redistribute; the only change is to +replace 'double' with a macro, 'FFTFLT', so that it can optionally +be run in single precision for greater speed. See Ooura's website +for another, more permissive-sounding copyright notice. -MSP +*/ + +/* ---------- Pd interface to OOURA FFT; imitate Mayer API ---------- */ +#include "m_pd.h" +#include "m_imp.h" + +#ifdef _WIN32 +# include /* MSVC or mingw on windows */ +#elif defined(__linux__) || defined(__APPLE__) +# include /* linux, mac, mingw, cygwin */ +#else +# include /* BSDs for example */ +#endif + +#define FFTFLT double +void cdft(int, int, FFTFLT *, int *, FFTFLT *); +void rdft(int, int, FFTFLT *, int *, FFTFLT *); + +int ilog2(int n); + +static PERTHREAD int ooura_maxn; +static PERTHREAD int *ooura_bitrev; +static PERTHREAD int ooura_bitrevsize; +static PERTHREAD FFTFLT *ooura_costab; + +static int ooura_init( int n) +{ + n = (1 << ilog2(n)); + if (n < 64) + return (0); + if (n > ooura_maxn) + { + if (n > ooura_maxn) /* recheck in case it got set while we waited */ + { + if (ooura_maxn) + { + t_freebytes(ooura_bitrev, ooura_bitrevsize); + t_freebytes(ooura_costab, ooura_maxn * sizeof(FFTFLT) / 2); + } + ooura_bitrevsize = sizeof(int) * (2 + (1 << (ilog2(n)/2))); + ooura_bitrev = (int *)t_getbytes(ooura_bitrevsize); + ooura_bitrev[0] = 0; + if (!ooura_bitrev) + { + error("out of memory allocating FFT buffer"); + ooura_maxn = 0; + return (0); + } + ooura_costab = (FFTFLT *)t_getbytes(n * sizeof(FFTFLT)/2); + if (!ooura_costab) + { + error("out of memory allocating FFT buffer"); + t_freebytes(ooura_bitrev, ooura_bitrevsize); + ooura_maxn = 0; + return (0); + } + ooura_maxn = n; + ooura_bitrev[0] = 0; + } + } + return (1); +} + +EXTERN void mayer_fht(t_sample *fz, int n) +{ + post("FHT: not yet implemented"); +} + +EXTERN void mayer_dofft(t_sample *fz1, t_sample *fz2, int n, int sgn) +{ + FFTFLT *buf, *fp3; + int i; + t_sample *fp1, *fp2; + buf = alloca(n * (2 * sizeof(FFTFLT))); + if (!ooura_init(2*n)) + return; + for (i = 0, fp1 = fz1, fp2 = fz2, fp3 = buf; i < n; i++) + { + fp3[0] = *fp1++; + fp3[1] = *fp2++; + fp3 += 2; + } + cdft(2*n, sgn, buf, ooura_bitrev, ooura_costab); + for (i = 0, fp1 = fz1, fp2 = fz2, fp3 = buf; i < n; i++) + { + *fp1++ = fp3[0]; + *fp2++ = fp3[1]; + fp3 += 2; + } +} + +EXTERN void mayer_fft(int n, t_sample *fz1, t_sample *fz2) +{ + mayer_dofft(fz1, fz2, n, -1); +} + +EXTERN void mayer_ifft(int n, t_sample *fz1, t_sample *fz2) +{ + mayer_dofft(fz1, fz2, n, 1); +} + +EXTERN void mayer_realfft(int n, t_sample *fz) +{ + FFTFLT *buf, *fp3; + int i, nover2 = n/2; + t_sample *fp1, *fp2; + buf = alloca(n * sizeof(FFTFLT)); + if (!ooura_init(n)) + return; + for (i = 0, fp1 = fz, fp3 = buf; i < n; i++, fp1++, fp3++) + buf[i] = fz[i]; + rdft(n, 1, buf, ooura_bitrev, ooura_costab); + fz[0] = buf[0]; + fz[nover2] = buf[1]; + for (i = 1, fp1 = fz+1, fp2 = fz+(n-1), fp3 = buf+2; i < nover2; + i++, fp1++, fp2--, fp3 += 2) + *fp1 = fp3[0], *fp2 = fp3[1]; +} + +EXTERN void mayer_realifft(int n, t_sample *fz) +{ + FFTFLT *buf, *fp3; + int i, nover2 = n/2; + t_sample *fp1, *fp2; + buf = alloca(n * sizeof(FFTFLT)); + if (!ooura_init(n)) + return; + buf[0] = fz[0]; + buf[1] = fz[nover2]; + for (i = 1, fp1 = fz+1, fp2 = fz+(n-1), fp3 = buf+2; i < nover2; + i++, fp1++, fp2--, fp3 += 2) + fp3[0] = *fp1, fp3[1] = *fp2; + rdft(n, -1, buf, ooura_bitrev, ooura_costab); + for (i = 0, fp1 = fz, fp3 = buf; i < n; i++, fp1++, fp3++) + fz[i] = 2*buf[i]; +} + + /* ancient ISPW-like version, used in fiddle~ and perhaps other externs + here and there. */ +void pd_fft(t_float *buf, int npoints, int inverse) +{ + FFTFLT *buf2 = (FFTFLT *)alloca(2 * npoints * sizeof(FFTFLT)), *bp2; + t_float *fp; + int i; + if (!ooura_init(2*npoints)) + return; + for (i = 0, bp2 = buf2, fp = buf; i < 2 * npoints; i++, bp2++, fp++) + *bp2 = *fp; + cdft(2*npoints, (inverse ? 1 : -1), buf2, ooura_bitrev, ooura_costab); + for (i = 0, bp2 = buf2, fp = buf; i < 2 * npoints; i++, bp2++, fp++) + *fp = *bp2; +} + +/****************** end Pd-specific prologue ***********************/ +/* +Fast Fourier/Cosine/Sine Transform + dimension :one + data length :power of 2 + decimation :frequency + radix :split-radix + data :inplace + table :use +functions + cdft: Complex Discrete Fourier Transform + rdft: Real Discrete Fourier Transform + ddct: Discrete Cosine Transform + ddst: Discrete Sine Transform + dfct: Cosine Transform of RDFT (Real Symmetric DFT) + dfst: Sine Transform of RDFT (Real Anti-symmetric DFT) +function prototypes + void cdft(int, int, FFTFLT *, int *, FFTFLT *); + void rdft(int, int, FFTFLT *, int *, FFTFLT *); + void ddct(int, int, FFTFLT *, int *, FFTFLT *); + void ddst(int, int, FFTFLT *, int *, FFTFLT *); + void dfct(int, FFTFLT *, FFTFLT *, int *, FFTFLT *); + void dfst(int, FFTFLT *, FFTFLT *, int *, FFTFLT *); +macro definitions + USE_CDFT_PTHREADS : default=not defined + CDFT_THREADS_BEGIN_N : must be >= 512, default=8192 + CDFT_4THREADS_BEGIN_N : must be >= 512, default=65536 + USE_CDFT_WINTHREADS : default=not defined + CDFT_THREADS_BEGIN_N : must be >= 512, default=32768 + CDFT_4THREADS_BEGIN_N : must be >= 512, default=524288 + + +-------- Complex DFT (Discrete Fourier Transform) -------- + [definition] + + X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k + X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k + ip[0] = 0; // first time only + cdft(2*n, 1, a, ip, w); + + ip[0] = 0; // first time only + cdft(2*n, -1, a, ip, w); + [parameters] + 2*n :data length (int) + n >= 1, n = power of 2 + a[0...2*n-1] :input/output data (FFTFLT *) + input data + a[2*j] = Re(x[j]), + a[2*j+1] = Im(x[j]), 0<=j= 2+sqrt(n) + strictly, + length of ip >= + 2+(1<<(int)(log(n+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n/2-1] :cos/sin table (FFTFLT *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + cdft(2*n, -1, a, ip, w); + is + cdft(2*n, 1, a, ip, w); + for (j = 0; j <= 2 * n - 1; j++) { + a[j] *= 1.0 / n; + } + . + + +-------- Real DFT / Inverse of Real DFT -------- + [definition] + RDFT + R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2 + I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0 IRDFT (excluding scale) + a[k] = (R[0] + R[n/2]*cos(pi*k))/2 + + sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) + + sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k + ip[0] = 0; // first time only + rdft(n, 1, a, ip, w); + + ip[0] = 0; // first time only + rdft(n, -1, a, ip, w); + [parameters] + n :data length (int) + n >= 2, n = power of 2 + a[0...n-1] :input/output data (FFTFLT *) + + output data + a[2*k] = R[k], 0<=k + input data + a[2*j] = R[j], 0<=j= 2+sqrt(n/2) + strictly, + length of ip >= + 2+(1<<(int)(log(n/2+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n/2-1] :cos/sin table (FFTFLT *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + rdft(n, 1, a, ip, w); + is + rdft(n, -1, a, ip, w); + for (j = 0; j <= n - 1; j++) { + a[j] *= 2.0 / n; + } + . + + +-------- DCT (Discrete Cosine Transform) / Inverse of DCT -------- + [definition] + IDCT (excluding scale) + C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k DCT + C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k + ip[0] = 0; // first time only + ddct(n, 1, a, ip, w); + + ip[0] = 0; // first time only + ddct(n, -1, a, ip, w); + [parameters] + n :data length (int) + n >= 2, n = power of 2 + a[0...n-1] :input/output data (FFTFLT *) + output data + a[k] = C[k], 0<=k= 2+sqrt(n/2) + strictly, + length of ip >= + 2+(1<<(int)(log(n/2+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n*5/4-1] :cos/sin table (FFTFLT *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + ddct(n, -1, a, ip, w); + is + a[0] *= 0.5; + ddct(n, 1, a, ip, w); + for (j = 0; j <= n - 1; j++) { + a[j] *= 2.0 / n; + } + . + + +-------- DST (Discrete Sine Transform) / Inverse of DST -------- + [definition] + IDST (excluding scale) + S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k DST + S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0 + ip[0] = 0; // first time only + ddst(n, 1, a, ip, w); + + ip[0] = 0; // first time only + ddst(n, -1, a, ip, w); + [parameters] + n :data length (int) + n >= 2, n = power of 2 + a[0...n-1] :input/output data (FFTFLT *) + + input data + a[j] = A[j], 0 + output data + a[k] = S[k], 0= 2+sqrt(n/2) + strictly, + length of ip >= + 2+(1<<(int)(log(n/2+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n*5/4-1] :cos/sin table (FFTFLT *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + ddst(n, -1, a, ip, w); + is + a[0] *= 0.5; + ddst(n, 1, a, ip, w); + for (j = 0; j <= n - 1; j++) { + a[j] *= 2.0 / n; + } + . + + +-------- Cosine Transform of RDFT (Real Symmetric DFT) -------- + [definition] + C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n + [usage] + ip[0] = 0; // first time only + dfct(n, a, t, ip, w); + [parameters] + n :data length - 1 (int) + n >= 2, n = power of 2 + a[0...n] :input/output data (FFTFLT *) + output data + a[k] = C[k], 0<=k<=n + t[0...n/2] :work area (FFTFLT *) + ip[0...*] :work area for bit reversal (int *) + length of ip >= 2+sqrt(n/4) + strictly, + length of ip >= + 2+(1<<(int)(log(n/4+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n*5/8-1] :cos/sin table (FFTFLT *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + a[0] *= 0.5; + a[n] *= 0.5; + dfct(n, a, t, ip, w); + is + a[0] *= 0.5; + a[n] *= 0.5; + dfct(n, a, t, ip, w); + for (j = 0; j <= n; j++) { + a[j] *= 2.0 / n; + } + . + + +-------- Sine Transform of RDFT (Real Anti-symmetric DFT) -------- + [definition] + S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0= 2, n = power of 2 + a[0...n-1] :input/output data (FFTFLT *) + output data + a[k] = S[k], 0= 2+sqrt(n/4) + strictly, + length of ip >= + 2+(1<<(int)(log(n/4+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n*5/8-1] :cos/sin table (FFTFLT *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + dfst(n, a, t, ip, w); + is + dfst(n, a, t, ip, w); + for (j = 1; j <= n - 1; j++) { + a[j] *= 2.0 / n; + } + . + + +Appendix : + The cos/sin table is recalculated when the larger table required. + w[] and ip[] are compatible with all routines. +*/ + + +void cdft(int n, int isgn, FFTFLT *a, int *ip, FFTFLT *w) +{ + void makewt(int nw, int *ip, FFTFLT *w); + void cftfsub(int n, FFTFLT *a, int *ip, int nw, FFTFLT *w); + void cftbsub(int n, FFTFLT *a, int *ip, int nw, FFTFLT *w); + int nw; + + nw = ip[0]; + if (n > (nw << 2)) { + nw = n >> 2; + makewt(nw, ip, w); + } + if (isgn >= 0) { + cftfsub(n, a, ip, nw, w); + } else { + cftbsub(n, a, ip, nw, w); + } +} + + +void rdft(int n, int isgn, FFTFLT *a, int *ip, FFTFLT *w) +{ + void makewt(int nw, int *ip, FFTFLT *w); + void makect(int nc, int *ip, FFTFLT *c); + void cftfsub(int n, FFTFLT *a, int *ip, int nw, FFTFLT *w); + void cftbsub(int n, FFTFLT *a, int *ip, int nw, FFTFLT *w); + void rftfsub(int n, FFTFLT *a, int nc, FFTFLT *c); + void rftbsub(int n, FFTFLT *a, int nc, FFTFLT *c); + int nw, nc; + FFTFLT xi; + + nw = ip[0]; + if (n > (nw << 2)) { + nw = n >> 2; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > (nc << 2)) { + nc = n >> 2; + makect(nc, ip, w + nw); + } + if (isgn >= 0) { + if (n > 4) { + cftfsub(n, a, ip, nw, w); + rftfsub(n, a, nc, w + nw); + } else if (n == 4) { + cftfsub(n, a, ip, nw, w); + } + xi = a[0] - a[1]; + a[0] += a[1]; + a[1] = xi; + } else { + a[1] = 0.5 * (a[0] - a[1]); + a[0] -= a[1]; + if (n > 4) { + rftbsub(n, a, nc, w + nw); + cftbsub(n, a, ip, nw, w); + } else if (n == 4) { + cftbsub(n, a, ip, nw, w); + } + } +} + + +void ddct(int n, int isgn, FFTFLT *a, int *ip, FFTFLT *w) +{ + void makewt(int nw, int *ip, FFTFLT *w); + void makect(int nc, int *ip, FFTFLT *c); + void cftfsub(int n, FFTFLT *a, int *ip, int nw, FFTFLT *w); + void cftbsub(int n, FFTFLT *a, int *ip, int nw, FFTFLT *w); + void rftfsub(int n, FFTFLT *a, int nc, FFTFLT *c); + void rftbsub(int n, FFTFLT *a, int nc, FFTFLT *c); + void dctsub(int n, FFTFLT *a, int nc, FFTFLT *c); + int j, nw, nc; + FFTFLT xr; + + nw = ip[0]; + if (n > (nw << 2)) { + nw = n >> 2; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > nc) { + nc = n; + makect(nc, ip, w + nw); + } + if (isgn < 0) { + xr = a[n - 1]; + for (j = n - 2; j >= 2; j -= 2) { + a[j + 1] = a[j] - a[j - 1]; + a[j] += a[j - 1]; + } + a[1] = a[0] - xr; + a[0] += xr; + if (n > 4) { + rftbsub(n, a, nc, w + nw); + cftbsub(n, a, ip, nw, w); + } else if (n == 4) { + cftbsub(n, a, ip, nw, w); + } + } + dctsub(n, a, nc, w + nw); + if (isgn >= 0) { + if (n > 4) { + cftfsub(n, a, ip, nw, w); + rftfsub(n, a, nc, w + nw); + } else if (n == 4) { + cftfsub(n, a, ip, nw, w); + } + xr = a[0] - a[1]; + a[0] += a[1]; + for (j = 2; j < n; j += 2) { + a[j - 1] = a[j] - a[j + 1]; + a[j] += a[j + 1]; + } + a[n - 1] = xr; + } +} + + +void ddst(int n, int isgn, FFTFLT *a, int *ip, FFTFLT *w) +{ + void makewt(int nw, int *ip, FFTFLT *w); + void makect(int nc, int *ip, FFTFLT *c); + void cftfsub(int n, FFTFLT *a, int *ip, int nw, FFTFLT *w); + void cftbsub(int n, FFTFLT *a, int *ip, int nw, FFTFLT *w); + void rftfsub(int n, FFTFLT *a, int nc, FFTFLT *c); + void rftbsub(int n, FFTFLT *a, int nc, FFTFLT *c); + void dstsub(int n, FFTFLT *a, int nc, FFTFLT *c); + int j, nw, nc; + FFTFLT xr; + + nw = ip[0]; + if (n > (nw << 2)) { + nw = n >> 2; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > nc) { + nc = n; + makect(nc, ip, w + nw); + } + if (isgn < 0) { + xr = a[n - 1]; + for (j = n - 2; j >= 2; j -= 2) { + a[j + 1] = -a[j] - a[j - 1]; + a[j] -= a[j - 1]; + } + a[1] = a[0] + xr; + a[0] -= xr; + if (n > 4) { + rftbsub(n, a, nc, w + nw); + cftbsub(n, a, ip, nw, w); + } else if (n == 4) { + cftbsub(n, a, ip, nw, w); + } + } + dstsub(n, a, nc, w + nw); + if (isgn >= 0) { + if (n > 4) { + cftfsub(n, a, ip, nw, w); + rftfsub(n, a, nc, w + nw); + } else if (n == 4) { + cftfsub(n, a, ip, nw, w); + } + xr = a[0] - a[1]; + a[0] += a[1]; + for (j = 2; j < n; j += 2) { + a[j - 1] = -a[j] - a[j + 1]; + a[j] -= a[j + 1]; + } + a[n - 1] = -xr; + } +} + + +void dfct(int n, FFTFLT *a, FFTFLT *t, int *ip, FFTFLT *w) +{ + void makewt(int nw, int *ip, FFTFLT *w); + void makect(int nc, int *ip, FFTFLT *c); + void cftfsub(int n, FFTFLT *a, int *ip, int nw, FFTFLT *w); + void rftfsub(int n, FFTFLT *a, int nc, FFTFLT *c); + void dctsub(int n, FFTFLT *a, int nc, FFTFLT *c); + int j, k, l, m, mh, nw, nc; + FFTFLT xr, xi, yr, yi; + + nw = ip[0]; + if (n > (nw << 3)) { + nw = n >> 3; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > (nc << 1)) { + nc = n >> 1; + makect(nc, ip, w + nw); + } + m = n >> 1; + yi = a[m]; + xi = a[0] + a[n]; + a[0] -= a[n]; + t[0] = xi - yi; + t[m] = xi + yi; + if (n > 2) { + mh = m >> 1; + for (j = 1; j < mh; j++) { + k = m - j; + xr = a[j] - a[n - j]; + xi = a[j] + a[n - j]; + yr = a[k] - a[n - k]; + yi = a[k] + a[n - k]; + a[j] = xr; + a[k] = yr; + t[j] = xi - yi; + t[k] = xi + yi; + } + t[mh] = a[mh] + a[n - mh]; + a[mh] -= a[n - mh]; + dctsub(m, a, nc, w + nw); + if (m > 4) { + cftfsub(m, a, ip, nw, w); + rftfsub(m, a, nc, w + nw); + } else if (m == 4) { + cftfsub(m, a, ip, nw, w); + } + a[n - 1] = a[0] - a[1]; + a[1] = a[0] + a[1]; + for (j = m - 2; j >= 2; j -= 2) { + a[2 * j + 1] = a[j] + a[j + 1]; + a[2 * j - 1] = a[j] - a[j + 1]; + } + l = 2; + m = mh; + while (m >= 2) { + dctsub(m, t, nc, w + nw); + if (m > 4) { + cftfsub(m, t, ip, nw, w); + rftfsub(m, t, nc, w + nw); + } else if (m == 4) { + cftfsub(m, t, ip, nw, w); + } + a[n - l] = t[0] - t[1]; + a[l] = t[0] + t[1]; + k = 0; + for (j = 2; j < m; j += 2) { + k += l << 2; + a[k - l] = t[j] - t[j + 1]; + a[k + l] = t[j] + t[j + 1]; + } + l <<= 1; + mh = m >> 1; + for (j = 0; j < mh; j++) { + k = m - j; + t[j] = t[m + k] - t[m + j]; + t[k] = t[m + k] + t[m + j]; + } + t[mh] = t[m + mh]; + m = mh; + } + a[l] = t[0]; + a[n] = t[2] - t[1]; + a[0] = t[2] + t[1]; + } else { + a[1] = a[0]; + a[2] = t[0]; + a[0] = t[1]; + } +} + + +void dfst(int n, FFTFLT *a, FFTFLT *t, int *ip, FFTFLT *w) +{ + void makewt(int nw, int *ip, FFTFLT *w); + void makect(int nc, int *ip, FFTFLT *c); + void cftfsub(int n, FFTFLT *a, int *ip, int nw, FFTFLT *w); + void rftfsub(int n, FFTFLT *a, int nc, FFTFLT *c); + void dstsub(int n, FFTFLT *a, int nc, FFTFLT *c); + int j, k, l, m, mh, nw, nc; + FFTFLT xr, xi, yr, yi; + + nw = ip[0]; + if (n > (nw << 3)) { + nw = n >> 3; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > (nc << 1)) { + nc = n >> 1; + makect(nc, ip, w + nw); + } + if (n > 2) { + m = n >> 1; + mh = m >> 1; + for (j = 1; j < mh; j++) { + k = m - j; + xr = a[j] + a[n - j]; + xi = a[j] - a[n - j]; + yr = a[k] + a[n - k]; + yi = a[k] - a[n - k]; + a[j] = xr; + a[k] = yr; + t[j] = xi + yi; + t[k] = xi - yi; + } + t[0] = a[mh] - a[n - mh]; + a[mh] += a[n - mh]; + a[0] = a[m]; + dstsub(m, a, nc, w + nw); + if (m > 4) { + cftfsub(m, a, ip, nw, w); + rftfsub(m, a, nc, w + nw); + } else if (m == 4) { + cftfsub(m, a, ip, nw, w); + } + a[n - 1] = a[1] - a[0]; + a[1] = a[0] + a[1]; + for (j = m - 2; j >= 2; j -= 2) { + a[2 * j + 1] = a[j] - a[j + 1]; + a[2 * j - 1] = -a[j] - a[j + 1]; + } + l = 2; + m = mh; + while (m >= 2) { + dstsub(m, t, nc, w + nw); + if (m > 4) { + cftfsub(m, t, ip, nw, w); + rftfsub(m, t, nc, w + nw); + } else if (m == 4) { + cftfsub(m, t, ip, nw, w); + } + a[n - l] = t[1] - t[0]; + a[l] = t[0] + t[1]; + k = 0; + for (j = 2; j < m; j += 2) { + k += l << 2; + a[k - l] = -t[j] - t[j + 1]; + a[k + l] = t[j] - t[j + 1]; + } + l <<= 1; + mh = m >> 1; + for (j = 1; j < mh; j++) { + k = m - j; + t[j] = t[m + k] + t[m + j]; + t[k] = t[m + k] - t[m + j]; + } + t[0] = t[m + mh]; + m = mh; + } + a[l] = t[0]; + } + a[0] = 0; +} + + +/* -------- initializing routines -------- */ + + +#include + +void makewt(int nw, int *ip, FFTFLT *w) +{ + void makeipt(int nw, int *ip); + int j, nwh, nw0, nw1; + FFTFLT delta, wn4r, wk1r, wk1i, wk3r, wk3i; + + ip[0] = nw; + ip[1] = 1; + if (nw > 2) { + nwh = nw >> 1; + delta = atan(1.0) / nwh; + wn4r = cos(delta * nwh); + w[0] = 1; + w[1] = wn4r; + if (nwh == 4) { + w[2] = cos(delta * 2); + w[3] = sin(delta * 2); + } else if (nwh > 4) { + makeipt(nw, ip); + w[2] = 0.5 / cos(delta * 2); + w[3] = 0.5 / cos(delta * 6); + for (j = 4; j < nwh; j += 4) { + w[j] = cos(delta * j); + w[j + 1] = sin(delta * j); + w[j + 2] = cos(3 * delta * j); + w[j + 3] = -sin(3 * delta * j); + } + } + nw0 = 0; + while (nwh > 2) { + nw1 = nw0 + nwh; + nwh >>= 1; + w[nw1] = 1; + w[nw1 + 1] = wn4r; + if (nwh == 4) { + wk1r = w[nw0 + 4]; + wk1i = w[nw0 + 5]; + w[nw1 + 2] = wk1r; + w[nw1 + 3] = wk1i; + } else if (nwh > 4) { + wk1r = w[nw0 + 4]; + wk3r = w[nw0 + 6]; + w[nw1 + 2] = 0.5 / wk1r; + w[nw1 + 3] = 0.5 / wk3r; + for (j = 4; j < nwh; j += 4) { + wk1r = w[nw0 + 2 * j]; + wk1i = w[nw0 + 2 * j + 1]; + wk3r = w[nw0 + 2 * j + 2]; + wk3i = w[nw0 + 2 * j + 3]; + w[nw1 + j] = wk1r; + w[nw1 + j + 1] = wk1i; + w[nw1 + j + 2] = wk3r; + w[nw1 + j + 3] = wk3i; + } + } + nw0 = nw1; + } + } +} + + +void makeipt(int nw, int *ip) +{ + int j, l, m, m2, p, q; + + ip[2] = 0; + ip[3] = 16; + m = 2; + for (l = nw; l > 32; l >>= 2) { + m2 = m << 1; + q = m2 << 3; + for (j = m; j < m2; j++) { + p = ip[j] << 2; + ip[m + j] = p; + ip[m2 + j] = p + q; + } + m = m2; + } +} + + +void makect(int nc, int *ip, FFTFLT *c) +{ + int j, nch; + FFTFLT delta; + + ip[1] = nc; + if (nc > 1) { + nch = nc >> 1; + delta = atan(1.0) / nch; + c[0] = cos(delta * nch); + c[nch] = 0.5 * c[0]; + for (j = 1; j < nch; j++) { + c[j] = 0.5 * cos(delta * j); + c[nc - j] = 0.5 * sin(delta * j); + } + } +} + + +/* -------- child routines -------- */ + + +#ifdef USE_CDFT_PTHREADS +#define USE_CDFT_THREADS +#ifndef CDFT_THREADS_BEGIN_N +#define CDFT_THREADS_BEGIN_N 8192 +#endif +#ifndef CDFT_4THREADS_BEGIN_N +#define CDFT_4THREADS_BEGIN_N 65536 +#endif +#include +#include +#include +#define cdft_thread_t pthread_t +#define cdft_thread_create(thp,func,argp) { \ + if (pthread_create(thp, NULL, func, (void *) argp) != 0) { \ + fprintf(stderr, "cdft thread error\n"); \ + exit(1); \ + } \ +} +#define cdft_thread_wait(th) { \ + if (pthread_join(th, NULL) != 0) { \ + fprintf(stderr, "cdft thread error\n"); \ + exit(1); \ + } \ +} +#endif /* USE_CDFT_PTHREADS */ + + +#ifdef USE_CDFT_WINTHREADS +#define USE_CDFT_THREADS +#ifndef CDFT_THREADS_BEGIN_N +#define CDFT_THREADS_BEGIN_N 32768 +#endif +#ifndef CDFT_4THREADS_BEGIN_N +#define CDFT_4THREADS_BEGIN_N 524288 +#endif +#include +#include +#include +#define cdft_thread_t HANDLE +#define cdft_thread_create(thp,func,argp) { \ + DWORD thid; \ + *(thp) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) func, (LPVOID) argp, 0, &thid); \ + if (*(thp) == 0) { \ + fprintf(stderr, "cdft thread error\n"); \ + exit(1); \ + } \ +} +#define cdft_thread_wait(th) { \ + WaitForSingleObject(th, INFINITE); \ + CloseHandle(th); \ +} +#endif /* USE_CDFT_WINTHREADS */ + + +void cftfsub(int n, FFTFLT *a, int *ip, int nw, FFTFLT *w) +{ + void bitrv2(int n, int *ip, FFTFLT *a); + void bitrv216(FFTFLT *a); + void bitrv208(FFTFLT *a); + void cftf1st(int n, FFTFLT *a, FFTFLT *w); + void cftrec4(int n, FFTFLT *a, int nw, FFTFLT *w); + void cftleaf(int n, int isplt, FFTFLT *a, int nw, FFTFLT *w); + void cftfx41(int n, FFTFLT *a, int nw, FFTFLT *w); + void cftf161(FFTFLT *a, FFTFLT *w); + void cftf081(FFTFLT *a, FFTFLT *w); + void cftf040(FFTFLT *a); + void cftx020(FFTFLT *a); +#ifdef USE_CDFT_THREADS + void cftrec4_th(int n, FFTFLT *a, int nw, FFTFLT *w); +#endif /* USE_CDFT_THREADS */ + + if (n > 8) { + if (n > 32) { + cftf1st(n, a, &w[nw - (n >> 2)]); +#ifdef USE_CDFT_THREADS + if (n > CDFT_THREADS_BEGIN_N) { + cftrec4_th(n, a, nw, w); + } else +#endif /* USE_CDFT_THREADS */ + if (n > 512) { + cftrec4(n, a, nw, w); + } else if (n > 128) { + cftleaf(n, 1, a, nw, w); + } else { + cftfx41(n, a, nw, w); + } + bitrv2(n, ip, a); + } else if (n == 32) { + cftf161(a, &w[nw - 8]); + bitrv216(a); + } else { + cftf081(a, w); + bitrv208(a); + } + } else if (n == 8) { + cftf040(a); + } else if (n == 4) { + cftx020(a); + } +} + + +void cftbsub(int n, FFTFLT *a, int *ip, int nw, FFTFLT *w) +{ + void bitrv2conj(int n, int *ip, FFTFLT *a); + void bitrv216neg(FFTFLT *a); + void bitrv208neg(FFTFLT *a); + void cftb1st(int n, FFTFLT *a, FFTFLT *w); + void cftrec4(int n, FFTFLT *a, int nw, FFTFLT *w); + void cftleaf(int n, int isplt, FFTFLT *a, int nw, FFTFLT *w); + void cftfx41(int n, FFTFLT *a, int nw, FFTFLT *w); + void cftf161(FFTFLT *a, FFTFLT *w); + void cftf081(FFTFLT *a, FFTFLT *w); + void cftb040(FFTFLT *a); + void cftx020(FFTFLT *a); +#ifdef USE_CDFT_THREADS + void cftrec4_th(int n, FFTFLT *a, int nw, FFTFLT *w); +#endif /* USE_CDFT_THREADS */ + + if (n > 8) { + if (n > 32) { + cftb1st(n, a, &w[nw - (n >> 2)]); +#ifdef USE_CDFT_THREADS + if (n > CDFT_THREADS_BEGIN_N) { + cftrec4_th(n, a, nw, w); + } else +#endif /* USE_CDFT_THREADS */ + if (n > 512) { + cftrec4(n, a, nw, w); + } else if (n > 128) { + cftleaf(n, 1, a, nw, w); + } else { + cftfx41(n, a, nw, w); + } + bitrv2conj(n, ip, a); + } else if (n == 32) { + cftf161(a, &w[nw - 8]); + bitrv216neg(a); + } else { + cftf081(a, w); + bitrv208neg(a); + } + } else if (n == 8) { + cftb040(a); + } else if (n == 4) { + cftx020(a); + } +} + + +void bitrv2(int n, int *ip, FFTFLT *a) +{ + int j, j1, k, k1, l, m, nh, nm; + FFTFLT xr, xi, yr, yi; + + m = 1; + for (l = n >> 2; l > 8; l >>= 2) { + m <<= 1; + } + nh = n >> 1; + nm = 4 * m; + if (l == 8) { + for (k = 0; k < m; k++) { + for (j = 0; j < k; j++) { + j1 = 4 * j + 2 * ip[m + k]; + k1 = 4 * k + 2 * ip[m + j]; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 += 2 * nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 -= nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 += 2 * nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nh; + k1 += 2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 -= 2 * nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 += nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 -= 2 * nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += 2; + k1 += nh; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 += 2 * nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 -= nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 += 2 * nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nh; + k1 -= 2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 -= 2 * nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 += nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 -= 2 * nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + k1 = 4 * k + 2 * ip[m + k]; + j1 = k1 + 2; + k1 += nh; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 += 2 * nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 -= nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= 2; + k1 -= nh; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nh + 2; + k1 += nh + 2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nh - nm; + k1 += 2 * nm - 2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + } else { + for (k = 0; k < m; k++) { + for (j = 0; j < k; j++) { + j1 = 4 * j + ip[m + k]; + k1 = 4 * k + ip[m + j]; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 += nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nh; + k1 += 2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 -= nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += 2; + k1 += nh; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 += nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nh; + k1 -= 2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 -= nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + k1 = 4 * k + ip[m + k]; + j1 = k1 + 2; + k1 += nh; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 += nm; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + } +} + + +void bitrv2conj(int n, int *ip, FFTFLT *a) +{ + int j, j1, k, k1, l, m, nh, nm; + FFTFLT xr, xi, yr, yi; + + m = 1; + for (l = n >> 2; l > 8; l >>= 2) { + m <<= 1; + } + nh = n >> 1; + nm = 4 * m; + if (l == 8) { + for (k = 0; k < m; k++) { + for (j = 0; j < k; j++) { + j1 = 4 * j + 2 * ip[m + k]; + k1 = 4 * k + 2 * ip[m + j]; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 += 2 * nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 -= nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 += 2 * nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nh; + k1 += 2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 -= 2 * nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 += nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 -= 2 * nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += 2; + k1 += nh; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 += 2 * nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 -= nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 += 2 * nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nh; + k1 -= 2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 -= 2 * nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 += nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 -= 2 * nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + k1 = 4 * k + 2 * ip[m + k]; + j1 = k1 + 2; + k1 += nh; + a[j1 - 1] = -a[j1 - 1]; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + a[k1 + 3] = -a[k1 + 3]; + j1 += nm; + k1 += 2 * nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 -= nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= 2; + k1 -= nh; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nh + 2; + k1 += nh + 2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nh - nm; + k1 += 2 * nm - 2; + a[j1 - 1] = -a[j1 - 1]; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + a[k1 + 3] = -a[k1 + 3]; + } + } else { + for (k = 0; k < m; k++) { + for (j = 0; j < k; j++) { + j1 = 4 * j + ip[m + k]; + k1 = 4 * k + ip[m + j]; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 += nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nh; + k1 += 2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 -= nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += 2; + k1 += nh; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nm; + k1 += nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nh; + k1 -= 2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nm; + k1 -= nm; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + k1 = 4 * k + ip[m + k]; + j1 = k1 + 2; + k1 += nh; + a[j1 - 1] = -a[j1 - 1]; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + a[k1 + 3] = -a[k1 + 3]; + j1 += nm; + k1 += nm; + a[j1 - 1] = -a[j1 - 1]; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + a[k1 + 3] = -a[k1 + 3]; + } + } +} + + +void bitrv216(FFTFLT *a) +{ + FFTFLT x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, + x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i, + x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i; + + x1r = a[2]; + x1i = a[3]; + x2r = a[4]; + x2i = a[5]; + x3r = a[6]; + x3i = a[7]; + x4r = a[8]; + x4i = a[9]; + x5r = a[10]; + x5i = a[11]; + x7r = a[14]; + x7i = a[15]; + x8r = a[16]; + x8i = a[17]; + x10r = a[20]; + x10i = a[21]; + x11r = a[22]; + x11i = a[23]; + x12r = a[24]; + x12i = a[25]; + x13r = a[26]; + x13i = a[27]; + x14r = a[28]; + x14i = a[29]; + a[2] = x8r; + a[3] = x8i; + a[4] = x4r; + a[5] = x4i; + a[6] = x12r; + a[7] = x12i; + a[8] = x2r; + a[9] = x2i; + a[10] = x10r; + a[11] = x10i; + a[14] = x14r; + a[15] = x14i; + a[16] = x1r; + a[17] = x1i; + a[20] = x5r; + a[21] = x5i; + a[22] = x13r; + a[23] = x13i; + a[24] = x3r; + a[25] = x3i; + a[26] = x11r; + a[27] = x11i; + a[28] = x7r; + a[29] = x7i; +} + + +void bitrv216neg(FFTFLT *a) +{ + FFTFLT x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, + x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i, + x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, + x13r, x13i, x14r, x14i, x15r, x15i; + + x1r = a[2]; + x1i = a[3]; + x2r = a[4]; + x2i = a[5]; + x3r = a[6]; + x3i = a[7]; + x4r = a[8]; + x4i = a[9]; + x5r = a[10]; + x5i = a[11]; + x6r = a[12]; + x6i = a[13]; + x7r = a[14]; + x7i = a[15]; + x8r = a[16]; + x8i = a[17]; + x9r = a[18]; + x9i = a[19]; + x10r = a[20]; + x10i = a[21]; + x11r = a[22]; + x11i = a[23]; + x12r = a[24]; + x12i = a[25]; + x13r = a[26]; + x13i = a[27]; + x14r = a[28]; + x14i = a[29]; + x15r = a[30]; + x15i = a[31]; + a[2] = x15r; + a[3] = x15i; + a[4] = x7r; + a[5] = x7i; + a[6] = x11r; + a[7] = x11i; + a[8] = x3r; + a[9] = x3i; + a[10] = x13r; + a[11] = x13i; + a[12] = x5r; + a[13] = x5i; + a[14] = x9r; + a[15] = x9i; + a[16] = x1r; + a[17] = x1i; + a[18] = x14r; + a[19] = x14i; + a[20] = x6r; + a[21] = x6i; + a[22] = x10r; + a[23] = x10i; + a[24] = x2r; + a[25] = x2i; + a[26] = x12r; + a[27] = x12i; + a[28] = x4r; + a[29] = x4i; + a[30] = x8r; + a[31] = x8i; +} + + +void bitrv208(FFTFLT *a) +{ + FFTFLT x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i; + + x1r = a[2]; + x1i = a[3]; + x3r = a[6]; + x3i = a[7]; + x4r = a[8]; + x4i = a[9]; + x6r = a[12]; + x6i = a[13]; + a[2] = x4r; + a[3] = x4i; + a[6] = x6r; + a[7] = x6i; + a[8] = x1r; + a[9] = x1i; + a[12] = x3r; + a[13] = x3i; +} + + +void bitrv208neg(FFTFLT *a) +{ + FFTFLT x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, + x5r, x5i, x6r, x6i, x7r, x7i; + + x1r = a[2]; + x1i = a[3]; + x2r = a[4]; + x2i = a[5]; + x3r = a[6]; + x3i = a[7]; + x4r = a[8]; + x4i = a[9]; + x5r = a[10]; + x5i = a[11]; + x6r = a[12]; + x6i = a[13]; + x7r = a[14]; + x7i = a[15]; + a[2] = x7r; + a[3] = x7i; + a[4] = x3r; + a[5] = x3i; + a[6] = x5r; + a[7] = x5i; + a[8] = x1r; + a[9] = x1i; + a[10] = x6r; + a[11] = x6i; + a[12] = x2r; + a[13] = x2i; + a[14] = x4r; + a[15] = x4i; +} + + +void cftf1st(int n, FFTFLT *a, FFTFLT *w) +{ + int j, j0, j1, j2, j3, k, m, mh; + FFTFLT wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, + wd1r, wd1i, wd3r, wd3i; + FFTFLT x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i; + + mh = n >> 3; + m = 2 * mh; + j1 = m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[0] + a[j2]; + x0i = a[1] + a[j2 + 1]; + x1r = a[0] - a[j2]; + x1i = a[1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + a[j2] = x1r - x3i; + a[j2 + 1] = x1i + x3r; + a[j3] = x1r + x3i; + a[j3 + 1] = x1i - x3r; + wn4r = w[1]; + csc1 = w[2]; + csc3 = w[3]; + wd1r = 1; + wd1i = 0; + wd3r = 1; + wd3i = 0; + k = 0; + for (j = 2; j < mh - 2; j += 4) { + k += 4; + wk1r = csc1 * (wd1r + w[k]); + wk1i = csc1 * (wd1i + w[k + 1]); + wk3r = csc3 * (wd3r + w[k + 2]); + wk3i = csc3 * (wd3i + w[k + 3]); + wd1r = w[k]; + wd1i = w[k + 1]; + wd3r = w[k + 2]; + wd3i = w[k + 3]; + j1 = j + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j] + a[j2]; + x0i = a[j + 1] + a[j2 + 1]; + x1r = a[j] - a[j2]; + x1i = a[j + 1] - a[j2 + 1]; + y0r = a[j + 2] + a[j2 + 2]; + y0i = a[j + 3] + a[j2 + 3]; + y1r = a[j + 2] - a[j2 + 2]; + y1i = a[j + 3] - a[j2 + 3]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + y2r = a[j1 + 2] + a[j3 + 2]; + y2i = a[j1 + 3] + a[j3 + 3]; + y3r = a[j1 + 2] - a[j3 + 2]; + y3i = a[j1 + 3] - a[j3 + 3]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + a[j + 2] = y0r + y2r; + a[j + 3] = y0i + y2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + a[j1 + 2] = y0r - y2r; + a[j1 + 3] = y0i - y2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = wk1r * x0r - wk1i * x0i; + a[j2 + 1] = wk1r * x0i + wk1i * x0r; + x0r = y1r - y3i; + x0i = y1i + y3r; + a[j2 + 2] = wd1r * x0r - wd1i * x0i; + a[j2 + 3] = wd1r * x0i + wd1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = wk3r * x0r + wk3i * x0i; + a[j3 + 1] = wk3r * x0i - wk3i * x0r; + x0r = y1r + y3i; + x0i = y1i - y3r; + a[j3 + 2] = wd3r * x0r + wd3i * x0i; + a[j3 + 3] = wd3r * x0i - wd3i * x0r; + j0 = m - j; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] + a[j2]; + x0i = a[j0 + 1] + a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = a[j0 + 1] - a[j2 + 1]; + y0r = a[j0 - 2] + a[j2 - 2]; + y0i = a[j0 - 1] + a[j2 - 1]; + y1r = a[j0 - 2] - a[j2 - 2]; + y1i = a[j0 - 1] - a[j2 - 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + y2r = a[j1 - 2] + a[j3 - 2]; + y2i = a[j1 - 1] + a[j3 - 1]; + y3r = a[j1 - 2] - a[j3 - 2]; + y3i = a[j1 - 1] - a[j3 - 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i + x2i; + a[j0 - 2] = y0r + y2r; + a[j0 - 1] = y0i + y2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + a[j1 - 2] = y0r - y2r; + a[j1 - 1] = y0i - y2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = wk1i * x0r - wk1r * x0i; + a[j2 + 1] = wk1i * x0i + wk1r * x0r; + x0r = y1r - y3i; + x0i = y1i + y3r; + a[j2 - 2] = wd1i * x0r - wd1r * x0i; + a[j2 - 1] = wd1i * x0i + wd1r * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = wk3i * x0r + wk3r * x0i; + a[j3 + 1] = wk3i * x0i - wk3r * x0r; + x0r = y1r + y3i; + x0i = y1i - y3r; + a[j3 - 2] = wd3i * x0r + wd3r * x0i; + a[j3 - 1] = wd3i * x0i - wd3r * x0r; + } + wk1r = csc1 * (wd1r + wn4r); + wk1i = csc1 * (wd1i + wn4r); + wk3r = csc3 * (wd3r - wn4r); + wk3i = csc3 * (wd3i - wn4r); + j0 = mh; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0 - 2] + a[j2 - 2]; + x0i = a[j0 - 1] + a[j2 - 1]; + x1r = a[j0 - 2] - a[j2 - 2]; + x1i = a[j0 - 1] - a[j2 - 1]; + x2r = a[j1 - 2] + a[j3 - 2]; + x2i = a[j1 - 1] + a[j3 - 1]; + x3r = a[j1 - 2] - a[j3 - 2]; + x3i = a[j1 - 1] - a[j3 - 1]; + a[j0 - 2] = x0r + x2r; + a[j0 - 1] = x0i + x2i; + a[j1 - 2] = x0r - x2r; + a[j1 - 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2 - 2] = wk1r * x0r - wk1i * x0i; + a[j2 - 1] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3 - 2] = wk3r * x0r + wk3i * x0i; + a[j3 - 1] = wk3r * x0i - wk3i * x0r; + x0r = a[j0] + a[j2]; + x0i = a[j0 + 1] + a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = a[j0 + 1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = wn4r * (x0r - x0i); + a[j2 + 1] = wn4r * (x0i + x0r); + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = -wn4r * (x0r + x0i); + a[j3 + 1] = -wn4r * (x0i - x0r); + x0r = a[j0 + 2] + a[j2 + 2]; + x0i = a[j0 + 3] + a[j2 + 3]; + x1r = a[j0 + 2] - a[j2 + 2]; + x1i = a[j0 + 3] - a[j2 + 3]; + x2r = a[j1 + 2] + a[j3 + 2]; + x2i = a[j1 + 3] + a[j3 + 3]; + x3r = a[j1 + 2] - a[j3 + 2]; + x3i = a[j1 + 3] - a[j3 + 3]; + a[j0 + 2] = x0r + x2r; + a[j0 + 3] = x0i + x2i; + a[j1 + 2] = x0r - x2r; + a[j1 + 3] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2 + 2] = wk1i * x0r - wk1r * x0i; + a[j2 + 3] = wk1i * x0i + wk1r * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3 + 2] = wk3i * x0r + wk3r * x0i; + a[j3 + 3] = wk3i * x0i - wk3r * x0r; +} + + +void cftb1st(int n, FFTFLT *a, FFTFLT *w) +{ + int j, j0, j1, j2, j3, k, m, mh; + FFTFLT wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, + wd1r, wd1i, wd3r, wd3i; + FFTFLT x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i; + + mh = n >> 3; + m = 2 * mh; + j1 = m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[0] + a[j2]; + x0i = -a[1] - a[j2 + 1]; + x1r = a[0] - a[j2]; + x1i = -a[1] + a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[0] = x0r + x2r; + a[1] = x0i - x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i + x2i; + a[j2] = x1r + x3i; + a[j2 + 1] = x1i + x3r; + a[j3] = x1r - x3i; + a[j3 + 1] = x1i - x3r; + wn4r = w[1]; + csc1 = w[2]; + csc3 = w[3]; + wd1r = 1; + wd1i = 0; + wd3r = 1; + wd3i = 0; + k = 0; + for (j = 2; j < mh - 2; j += 4) { + k += 4; + wk1r = csc1 * (wd1r + w[k]); + wk1i = csc1 * (wd1i + w[k + 1]); + wk3r = csc3 * (wd3r + w[k + 2]); + wk3i = csc3 * (wd3i + w[k + 3]); + wd1r = w[k]; + wd1i = w[k + 1]; + wd3r = w[k + 2]; + wd3i = w[k + 3]; + j1 = j + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j] + a[j2]; + x0i = -a[j + 1] - a[j2 + 1]; + x1r = a[j] - a[j2]; + x1i = -a[j + 1] + a[j2 + 1]; + y0r = a[j + 2] + a[j2 + 2]; + y0i = -a[j + 3] - a[j2 + 3]; + y1r = a[j + 2] - a[j2 + 2]; + y1i = -a[j + 3] + a[j2 + 3]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + y2r = a[j1 + 2] + a[j3 + 2]; + y2i = a[j1 + 3] + a[j3 + 3]; + y3r = a[j1 + 2] - a[j3 + 2]; + y3i = a[j1 + 3] - a[j3 + 3]; + a[j] = x0r + x2r; + a[j + 1] = x0i - x2i; + a[j + 2] = y0r + y2r; + a[j + 3] = y0i - y2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i + x2i; + a[j1 + 2] = y0r - y2r; + a[j1 + 3] = y0i + y2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2] = wk1r * x0r - wk1i * x0i; + a[j2 + 1] = wk1r * x0i + wk1i * x0r; + x0r = y1r + y3i; + x0i = y1i + y3r; + a[j2 + 2] = wd1r * x0r - wd1i * x0i; + a[j2 + 3] = wd1r * x0i + wd1i * x0r; + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3] = wk3r * x0r + wk3i * x0i; + a[j3 + 1] = wk3r * x0i - wk3i * x0r; + x0r = y1r - y3i; + x0i = y1i - y3r; + a[j3 + 2] = wd3r * x0r + wd3i * x0i; + a[j3 + 3] = wd3r * x0i - wd3i * x0r; + j0 = m - j; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] + a[j2]; + x0i = -a[j0 + 1] - a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = -a[j0 + 1] + a[j2 + 1]; + y0r = a[j0 - 2] + a[j2 - 2]; + y0i = -a[j0 - 1] - a[j2 - 1]; + y1r = a[j0 - 2] - a[j2 - 2]; + y1i = -a[j0 - 1] + a[j2 - 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + y2r = a[j1 - 2] + a[j3 - 2]; + y2i = a[j1 - 1] + a[j3 - 1]; + y3r = a[j1 - 2] - a[j3 - 2]; + y3i = a[j1 - 1] - a[j3 - 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i - x2i; + a[j0 - 2] = y0r + y2r; + a[j0 - 1] = y0i - y2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i + x2i; + a[j1 - 2] = y0r - y2r; + a[j1 - 1] = y0i + y2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2] = wk1i * x0r - wk1r * x0i; + a[j2 + 1] = wk1i * x0i + wk1r * x0r; + x0r = y1r + y3i; + x0i = y1i + y3r; + a[j2 - 2] = wd1i * x0r - wd1r * x0i; + a[j2 - 1] = wd1i * x0i + wd1r * x0r; + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3] = wk3i * x0r + wk3r * x0i; + a[j3 + 1] = wk3i * x0i - wk3r * x0r; + x0r = y1r - y3i; + x0i = y1i - y3r; + a[j3 - 2] = wd3i * x0r + wd3r * x0i; + a[j3 - 1] = wd3i * x0i - wd3r * x0r; + } + wk1r = csc1 * (wd1r + wn4r); + wk1i = csc1 * (wd1i + wn4r); + wk3r = csc3 * (wd3r - wn4r); + wk3i = csc3 * (wd3i - wn4r); + j0 = mh; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0 - 2] + a[j2 - 2]; + x0i = -a[j0 - 1] - a[j2 - 1]; + x1r = a[j0 - 2] - a[j2 - 2]; + x1i = -a[j0 - 1] + a[j2 - 1]; + x2r = a[j1 - 2] + a[j3 - 2]; + x2i = a[j1 - 1] + a[j3 - 1]; + x3r = a[j1 - 2] - a[j3 - 2]; + x3i = a[j1 - 1] - a[j3 - 1]; + a[j0 - 2] = x0r + x2r; + a[j0 - 1] = x0i - x2i; + a[j1 - 2] = x0r - x2r; + a[j1 - 1] = x0i + x2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2 - 2] = wk1r * x0r - wk1i * x0i; + a[j2 - 1] = wk1r * x0i + wk1i * x0r; + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3 - 2] = wk3r * x0r + wk3i * x0i; + a[j3 - 1] = wk3r * x0i - wk3i * x0r; + x0r = a[j0] + a[j2]; + x0i = -a[j0 + 1] - a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = -a[j0 + 1] + a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i - x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i + x2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2] = wn4r * (x0r - x0i); + a[j2 + 1] = wn4r * (x0i + x0r); + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3] = -wn4r * (x0r + x0i); + a[j3 + 1] = -wn4r * (x0i - x0r); + x0r = a[j0 + 2] + a[j2 + 2]; + x0i = -a[j0 + 3] - a[j2 + 3]; + x1r = a[j0 + 2] - a[j2 + 2]; + x1i = -a[j0 + 3] + a[j2 + 3]; + x2r = a[j1 + 2] + a[j3 + 2]; + x2i = a[j1 + 3] + a[j3 + 3]; + x3r = a[j1 + 2] - a[j3 + 2]; + x3i = a[j1 + 3] - a[j3 + 3]; + a[j0 + 2] = x0r + x2r; + a[j0 + 3] = x0i - x2i; + a[j1 + 2] = x0r - x2r; + a[j1 + 3] = x0i + x2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2 + 2] = wk1i * x0r - wk1r * x0i; + a[j2 + 3] = wk1i * x0i + wk1r * x0r; + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3 + 2] = wk3i * x0r + wk3r * x0i; + a[j3 + 3] = wk3i * x0i - wk3r * x0r; +} + + +#ifdef USE_CDFT_THREADS +struct cdft_arg_st { + int n0; + int n; + FFTFLT *a; + int nw; + FFTFLT *w; +}; +typedef struct cdft_arg_st cdft_arg_t; + + +void cftrec4_th(int n, FFTFLT *a, int nw, FFTFLT *w) +{ + void *cftrec1_th(void *p); + void *cftrec2_th(void *p); + int i, idiv4, m, nthread; + cdft_thread_t th[4]; + cdft_arg_t ag[4]; + + nthread = 2; + idiv4 = 0; + m = n >> 1; + if (n > CDFT_4THREADS_BEGIN_N) { + nthread = 4; + idiv4 = 1; + m >>= 1; + } + for (i = 0; i < nthread; i++) { + ag[i].n0 = n; + ag[i].n = m; + ag[i].a = &a[i * m]; + ag[i].nw = nw; + ag[i].w = w; + if (i != idiv4) { + cdft_thread_create(&th[i], cftrec1_th, &ag[i]); + } else { + cdft_thread_create(&th[i], cftrec2_th, &ag[i]); + } + } + for (i = 0; i < nthread; i++) { + cdft_thread_wait(th[i]); + } +} + + +void *cftrec1_th(void *p) +{ + int cfttree(int n, int j, int k, FFTFLT *a, int nw, FFTFLT *w); + void cftleaf(int n, int isplt, FFTFLT *a, int nw, FFTFLT *w); + void cftmdl1(int n, FFTFLT *a, FFTFLT *w); + int isplt, j, k, m, n, n0, nw; + FFTFLT *a, *w; + + n0 = ((cdft_arg_t *) p)->n0; + n = ((cdft_arg_t *) p)->n; + a = ((cdft_arg_t *) p)->a; + nw = ((cdft_arg_t *) p)->nw; + w = ((cdft_arg_t *) p)->w; + m = n0; + while (m > 512) { + m >>= 2; + cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]); + } + cftleaf(m, 1, &a[n - m], nw, w); + k = 0; + for (j = n - m; j > 0; j -= m) { + k++; + isplt = cfttree(m, j, k, a, nw, w); + cftleaf(m, isplt, &a[j - m], nw, w); + } + return (void *) 0; +} + + +void *cftrec2_th(void *p) +{ + int cfttree(int n, int j, int k, FFTFLT *a, int nw, FFTFLT *w); + void cftleaf(int n, int isplt, FFTFLT *a, int nw, FFTFLT *w); + void cftmdl2(int n, FFTFLT *a, FFTFLT *w); + int isplt, j, k, m, n, n0, nw; + FFTFLT *a, *w; + + n0 = ((cdft_arg_t *) p)->n0; + n = ((cdft_arg_t *) p)->n; + a = ((cdft_arg_t *) p)->a; + nw = ((cdft_arg_t *) p)->nw; + w = ((cdft_arg_t *) p)->w; + k = 1; + m = n0; + while (m > 512) { + m >>= 2; + k <<= 2; + cftmdl2(m, &a[n - m], &w[nw - m]); + } + cftleaf(m, 0, &a[n - m], nw, w); + k >>= 1; + for (j = n - m; j > 0; j -= m) { + k++; + isplt = cfttree(m, j, k, a, nw, w); + cftleaf(m, isplt, &a[j - m], nw, w); + } + return (void *) 0; +} +#endif /* USE_CDFT_THREADS */ + + +void cftrec4(int n, FFTFLT *a, int nw, FFTFLT *w) +{ + int cfttree(int n, int j, int k, FFTFLT *a, int nw, FFTFLT *w); + void cftleaf(int n, int isplt, FFTFLT *a, int nw, FFTFLT *w); + void cftmdl1(int n, FFTFLT *a, FFTFLT *w); + int isplt, j, k, m; + + m = n; + while (m > 512) { + m >>= 2; + cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]); + } + cftleaf(m, 1, &a[n - m], nw, w); + k = 0; + for (j = n - m; j > 0; j -= m) { + k++; + isplt = cfttree(m, j, k, a, nw, w); + cftleaf(m, isplt, &a[j - m], nw, w); + } +} + + +int cfttree(int n, int j, int k, FFTFLT *a, int nw, FFTFLT *w) +{ + void cftmdl1(int n, FFTFLT *a, FFTFLT *w); + void cftmdl2(int n, FFTFLT *a, FFTFLT *w); + int i, isplt, m; + + if ((k & 3) != 0) { + isplt = k & 1; + if (isplt != 0) { + cftmdl1(n, &a[j - n], &w[nw - (n >> 1)]); + } else { + cftmdl2(n, &a[j - n], &w[nw - n]); + } + } else { + m = n; + for (i = k; (i & 3) == 0; i >>= 2) { + m <<= 2; + } + isplt = i & 1; + if (isplt != 0) { + while (m > 128) { + cftmdl1(m, &a[j - m], &w[nw - (m >> 1)]); + m >>= 2; + } + } else { + while (m > 128) { + cftmdl2(m, &a[j - m], &w[nw - m]); + m >>= 2; + } + } + } + return isplt; +} + + +void cftleaf(int n, int isplt, FFTFLT *a, int nw, FFTFLT *w) +{ + void cftmdl1(int n, FFTFLT *a, FFTFLT *w); + void cftmdl2(int n, FFTFLT *a, FFTFLT *w); + void cftf161(FFTFLT *a, FFTFLT *w); + void cftf162(FFTFLT *a, FFTFLT *w); + void cftf081(FFTFLT *a, FFTFLT *w); + void cftf082(FFTFLT *a, FFTFLT *w); + + if (n == 512) { + cftmdl1(128, a, &w[nw - 64]); + cftf161(a, &w[nw - 8]); + cftf162(&a[32], &w[nw - 32]); + cftf161(&a[64], &w[nw - 8]); + cftf161(&a[96], &w[nw - 8]); + cftmdl2(128, &a[128], &w[nw - 128]); + cftf161(&a[128], &w[nw - 8]); + cftf162(&a[160], &w[nw - 32]); + cftf161(&a[192], &w[nw - 8]); + cftf162(&a[224], &w[nw - 32]); + cftmdl1(128, &a[256], &w[nw - 64]); + cftf161(&a[256], &w[nw - 8]); + cftf162(&a[288], &w[nw - 32]); + cftf161(&a[320], &w[nw - 8]); + cftf161(&a[352], &w[nw - 8]); + if (isplt != 0) { + cftmdl1(128, &a[384], &w[nw - 64]); + cftf161(&a[480], &w[nw - 8]); + } else { + cftmdl2(128, &a[384], &w[nw - 128]); + cftf162(&a[480], &w[nw - 32]); + } + cftf161(&a[384], &w[nw - 8]); + cftf162(&a[416], &w[nw - 32]); + cftf161(&a[448], &w[nw - 8]); + } else { + cftmdl1(64, a, &w[nw - 32]); + cftf081(a, &w[nw - 8]); + cftf082(&a[16], &w[nw - 8]); + cftf081(&a[32], &w[nw - 8]); + cftf081(&a[48], &w[nw - 8]); + cftmdl2(64, &a[64], &w[nw - 64]); + cftf081(&a[64], &w[nw - 8]); + cftf082(&a[80], &w[nw - 8]); + cftf081(&a[96], &w[nw - 8]); + cftf082(&a[112], &w[nw - 8]); + cftmdl1(64, &a[128], &w[nw - 32]); + cftf081(&a[128], &w[nw - 8]); + cftf082(&a[144], &w[nw - 8]); + cftf081(&a[160], &w[nw - 8]); + cftf081(&a[176], &w[nw - 8]); + if (isplt != 0) { + cftmdl1(64, &a[192], &w[nw - 32]); + cftf081(&a[240], &w[nw - 8]); + } else { + cftmdl2(64, &a[192], &w[nw - 64]); + cftf082(&a[240], &w[nw - 8]); + } + cftf081(&a[192], &w[nw - 8]); + cftf082(&a[208], &w[nw - 8]); + cftf081(&a[224], &w[nw - 8]); + } +} + + +void cftmdl1(int n, FFTFLT *a, FFTFLT *w) +{ + int j, j0, j1, j2, j3, k, m, mh; + FFTFLT wn4r, wk1r, wk1i, wk3r, wk3i; + FFTFLT x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + mh = n >> 3; + m = 2 * mh; + j1 = m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[0] + a[j2]; + x0i = a[1] + a[j2 + 1]; + x1r = a[0] - a[j2]; + x1i = a[1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + a[j2] = x1r - x3i; + a[j2 + 1] = x1i + x3r; + a[j3] = x1r + x3i; + a[j3 + 1] = x1i - x3r; + wn4r = w[1]; + k = 0; + for (j = 2; j < mh; j += 2) { + k += 4; + wk1r = w[k]; + wk1i = w[k + 1]; + wk3r = w[k + 2]; + wk3i = w[k + 3]; + j1 = j + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j] + a[j2]; + x0i = a[j + 1] + a[j2 + 1]; + x1r = a[j] - a[j2]; + x1i = a[j + 1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = wk1r * x0r - wk1i * x0i; + a[j2 + 1] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = wk3r * x0r + wk3i * x0i; + a[j3 + 1] = wk3r * x0i - wk3i * x0r; + j0 = m - j; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] + a[j2]; + x0i = a[j0 + 1] + a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = a[j0 + 1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = wk1i * x0r - wk1r * x0i; + a[j2 + 1] = wk1i * x0i + wk1r * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = wk3i * x0r + wk3r * x0i; + a[j3 + 1] = wk3i * x0i - wk3r * x0r; + } + j0 = mh; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] + a[j2]; + x0i = a[j0 + 1] + a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = a[j0 + 1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = wn4r * (x0r - x0i); + a[j2 + 1] = wn4r * (x0i + x0r); + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = -wn4r * (x0r + x0i); + a[j3 + 1] = -wn4r * (x0i - x0r); +} + + +void cftmdl2(int n, FFTFLT *a, FFTFLT *w) +{ + int j, j0, j1, j2, j3, k, kr, m, mh; + FFTFLT wn4r, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i; + FFTFLT x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y2r, y2i; + + mh = n >> 3; + m = 2 * mh; + wn4r = w[1]; + j1 = m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[0] - a[j2 + 1]; + x0i = a[1] + a[j2]; + x1r = a[0] + a[j2 + 1]; + x1i = a[1] - a[j2]; + x2r = a[j1] - a[j3 + 1]; + x2i = a[j1 + 1] + a[j3]; + x3r = a[j1] + a[j3 + 1]; + x3i = a[j1 + 1] - a[j3]; + y0r = wn4r * (x2r - x2i); + y0i = wn4r * (x2i + x2r); + a[0] = x0r + y0r; + a[1] = x0i + y0i; + a[j1] = x0r - y0r; + a[j1 + 1] = x0i - y0i; + y0r = wn4r * (x3r - x3i); + y0i = wn4r * (x3i + x3r); + a[j2] = x1r - y0i; + a[j2 + 1] = x1i + y0r; + a[j3] = x1r + y0i; + a[j3 + 1] = x1i - y0r; + k = 0; + kr = 2 * m; + for (j = 2; j < mh; j += 2) { + k += 4; + wk1r = w[k]; + wk1i = w[k + 1]; + wk3r = w[k + 2]; + wk3i = w[k + 3]; + kr -= 4; + wd1i = w[kr]; + wd1r = w[kr + 1]; + wd3i = w[kr + 2]; + wd3r = w[kr + 3]; + j1 = j + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j] - a[j2 + 1]; + x0i = a[j + 1] + a[j2]; + x1r = a[j] + a[j2 + 1]; + x1i = a[j + 1] - a[j2]; + x2r = a[j1] - a[j3 + 1]; + x2i = a[j1 + 1] + a[j3]; + x3r = a[j1] + a[j3 + 1]; + x3i = a[j1 + 1] - a[j3]; + y0r = wk1r * x0r - wk1i * x0i; + y0i = wk1r * x0i + wk1i * x0r; + y2r = wd1r * x2r - wd1i * x2i; + y2i = wd1r * x2i + wd1i * x2r; + a[j] = y0r + y2r; + a[j + 1] = y0i + y2i; + a[j1] = y0r - y2r; + a[j1 + 1] = y0i - y2i; + y0r = wk3r * x1r + wk3i * x1i; + y0i = wk3r * x1i - wk3i * x1r; + y2r = wd3r * x3r + wd3i * x3i; + y2i = wd3r * x3i - wd3i * x3r; + a[j2] = y0r + y2r; + a[j2 + 1] = y0i + y2i; + a[j3] = y0r - y2r; + a[j3 + 1] = y0i - y2i; + j0 = m - j; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] - a[j2 + 1]; + x0i = a[j0 + 1] + a[j2]; + x1r = a[j0] + a[j2 + 1]; + x1i = a[j0 + 1] - a[j2]; + x2r = a[j1] - a[j3 + 1]; + x2i = a[j1 + 1] + a[j3]; + x3r = a[j1] + a[j3 + 1]; + x3i = a[j1 + 1] - a[j3]; + y0r = wd1i * x0r - wd1r * x0i; + y0i = wd1i * x0i + wd1r * x0r; + y2r = wk1i * x2r - wk1r * x2i; + y2i = wk1i * x2i + wk1r * x2r; + a[j0] = y0r + y2r; + a[j0 + 1] = y0i + y2i; + a[j1] = y0r - y2r; + a[j1 + 1] = y0i - y2i; + y0r = wd3i * x1r + wd3r * x1i; + y0i = wd3i * x1i - wd3r * x1r; + y2r = wk3i * x3r + wk3r * x3i; + y2i = wk3i * x3i - wk3r * x3r; + a[j2] = y0r + y2r; + a[j2 + 1] = y0i + y2i; + a[j3] = y0r - y2r; + a[j3 + 1] = y0i - y2i; + } + wk1r = w[m]; + wk1i = w[m + 1]; + j0 = mh; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] - a[j2 + 1]; + x0i = a[j0 + 1] + a[j2]; + x1r = a[j0] + a[j2 + 1]; + x1i = a[j0 + 1] - a[j2]; + x2r = a[j1] - a[j3 + 1]; + x2i = a[j1 + 1] + a[j3]; + x3r = a[j1] + a[j3 + 1]; + x3i = a[j1 + 1] - a[j3]; + y0r = wk1r * x0r - wk1i * x0i; + y0i = wk1r * x0i + wk1i * x0r; + y2r = wk1i * x2r - wk1r * x2i; + y2i = wk1i * x2i + wk1r * x2r; + a[j0] = y0r + y2r; + a[j0 + 1] = y0i + y2i; + a[j1] = y0r - y2r; + a[j1 + 1] = y0i - y2i; + y0r = wk1i * x1r - wk1r * x1i; + y0i = wk1i * x1i + wk1r * x1r; + y2r = wk1r * x3r - wk1i * x3i; + y2i = wk1r * x3i + wk1i * x3r; + a[j2] = y0r - y2r; + a[j2 + 1] = y0i - y2i; + a[j3] = y0r + y2r; + a[j3 + 1] = y0i + y2i; +} + + +void cftfx41(int n, FFTFLT *a, int nw, FFTFLT *w) +{ + void cftf161(FFTFLT *a, FFTFLT *w); + void cftf162(FFTFLT *a, FFTFLT *w); + void cftf081(FFTFLT *a, FFTFLT *w); + void cftf082(FFTFLT *a, FFTFLT *w); + + if (n == 128) { + cftf161(a, &w[nw - 8]); + cftf162(&a[32], &w[nw - 32]); + cftf161(&a[64], &w[nw - 8]); + cftf161(&a[96], &w[nw - 8]); + } else { + cftf081(a, &w[nw - 8]); + cftf082(&a[16], &w[nw - 8]); + cftf081(&a[32], &w[nw - 8]); + cftf081(&a[48], &w[nw - 8]); + } +} + + +void cftf161(FFTFLT *a, FFTFLT *w) +{ + FFTFLT wn4r, wk1r, wk1i, + x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, + y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, + y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, + y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; + + wn4r = w[1]; + wk1r = w[2]; + wk1i = w[3]; + x0r = a[0] + a[16]; + x0i = a[1] + a[17]; + x1r = a[0] - a[16]; + x1i = a[1] - a[17]; + x2r = a[8] + a[24]; + x2i = a[9] + a[25]; + x3r = a[8] - a[24]; + x3i = a[9] - a[25]; + y0r = x0r + x2r; + y0i = x0i + x2i; + y4r = x0r - x2r; + y4i = x0i - x2i; + y8r = x1r - x3i; + y8i = x1i + x3r; + y12r = x1r + x3i; + y12i = x1i - x3r; + x0r = a[2] + a[18]; + x0i = a[3] + a[19]; + x1r = a[2] - a[18]; + x1i = a[3] - a[19]; + x2r = a[10] + a[26]; + x2i = a[11] + a[27]; + x3r = a[10] - a[26]; + x3i = a[11] - a[27]; + y1r = x0r + x2r; + y1i = x0i + x2i; + y5r = x0r - x2r; + y5i = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + y9r = wk1r * x0r - wk1i * x0i; + y9i = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + y13r = wk1i * x0r - wk1r * x0i; + y13i = wk1i * x0i + wk1r * x0r; + x0r = a[4] + a[20]; + x0i = a[5] + a[21]; + x1r = a[4] - a[20]; + x1i = a[5] - a[21]; + x2r = a[12] + a[28]; + x2i = a[13] + a[29]; + x3r = a[12] - a[28]; + x3i = a[13] - a[29]; + y2r = x0r + x2r; + y2i = x0i + x2i; + y6r = x0r - x2r; + y6i = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + y10r = wn4r * (x0r - x0i); + y10i = wn4r * (x0i + x0r); + x0r = x1r + x3i; + x0i = x1i - x3r; + y14r = wn4r * (x0r + x0i); + y14i = wn4r * (x0i - x0r); + x0r = a[6] + a[22]; + x0i = a[7] + a[23]; + x1r = a[6] - a[22]; + x1i = a[7] - a[23]; + x2r = a[14] + a[30]; + x2i = a[15] + a[31]; + x3r = a[14] - a[30]; + x3i = a[15] - a[31]; + y3r = x0r + x2r; + y3i = x0i + x2i; + y7r = x0r - x2r; + y7i = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + y11r = wk1i * x0r - wk1r * x0i; + y11i = wk1i * x0i + wk1r * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + y15r = wk1r * x0r - wk1i * x0i; + y15i = wk1r * x0i + wk1i * x0r; + x0r = y12r - y14r; + x0i = y12i - y14i; + x1r = y12r + y14r; + x1i = y12i + y14i; + x2r = y13r - y15r; + x2i = y13i - y15i; + x3r = y13r + y15r; + x3i = y13i + y15i; + a[24] = x0r + x2r; + a[25] = x0i + x2i; + a[26] = x0r - x2r; + a[27] = x0i - x2i; + a[28] = x1r - x3i; + a[29] = x1i + x3r; + a[30] = x1r + x3i; + a[31] = x1i - x3r; + x0r = y8r + y10r; + x0i = y8i + y10i; + x1r = y8r - y10r; + x1i = y8i - y10i; + x2r = y9r + y11r; + x2i = y9i + y11i; + x3r = y9r - y11r; + x3i = y9i - y11i; + a[16] = x0r + x2r; + a[17] = x0i + x2i; + a[18] = x0r - x2r; + a[19] = x0i - x2i; + a[20] = x1r - x3i; + a[21] = x1i + x3r; + a[22] = x1r + x3i; + a[23] = x1i - x3r; + x0r = y5r - y7i; + x0i = y5i + y7r; + x2r = wn4r * (x0r - x0i); + x2i = wn4r * (x0i + x0r); + x0r = y5r + y7i; + x0i = y5i - y7r; + x3r = wn4r * (x0r - x0i); + x3i = wn4r * (x0i + x0r); + x0r = y4r - y6i; + x0i = y4i + y6r; + x1r = y4r + y6i; + x1i = y4i - y6r; + a[8] = x0r + x2r; + a[9] = x0i + x2i; + a[10] = x0r - x2r; + a[11] = x0i - x2i; + a[12] = x1r - x3i; + a[13] = x1i + x3r; + a[14] = x1r + x3i; + a[15] = x1i - x3r; + x0r = y0r + y2r; + x0i = y0i + y2i; + x1r = y0r - y2r; + x1i = y0i - y2i; + x2r = y1r + y3r; + x2i = y1i + y3i; + x3r = y1r - y3r; + x3i = y1i - y3i; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[2] = x0r - x2r; + a[3] = x0i - x2i; + a[4] = x1r - x3i; + a[5] = x1i + x3r; + a[6] = x1r + x3i; + a[7] = x1i - x3r; +} + + +void cftf162(FFTFLT *a, FFTFLT *w) +{ + FFTFLT wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, + x0r, x0i, x1r, x1i, x2r, x2i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, + y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, + y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, + y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; + + wn4r = w[1]; + wk1r = w[4]; + wk1i = w[5]; + wk3r = w[6]; + wk3i = -w[7]; + wk2r = w[8]; + wk2i = w[9]; + x1r = a[0] - a[17]; + x1i = a[1] + a[16]; + x0r = a[8] - a[25]; + x0i = a[9] + a[24]; + x2r = wn4r * (x0r - x0i); + x2i = wn4r * (x0i + x0r); + y0r = x1r + x2r; + y0i = x1i + x2i; + y4r = x1r - x2r; + y4i = x1i - x2i; + x1r = a[0] + a[17]; + x1i = a[1] - a[16]; + x0r = a[8] + a[25]; + x0i = a[9] - a[24]; + x2r = wn4r * (x0r - x0i); + x2i = wn4r * (x0i + x0r); + y8r = x1r - x2i; + y8i = x1i + x2r; + y12r = x1r + x2i; + y12i = x1i - x2r; + x0r = a[2] - a[19]; + x0i = a[3] + a[18]; + x1r = wk1r * x0r - wk1i * x0i; + x1i = wk1r * x0i + wk1i * x0r; + x0r = a[10] - a[27]; + x0i = a[11] + a[26]; + x2r = wk3i * x0r - wk3r * x0i; + x2i = wk3i * x0i + wk3r * x0r; + y1r = x1r + x2r; + y1i = x1i + x2i; + y5r = x1r - x2r; + y5i = x1i - x2i; + x0r = a[2] + a[19]; + x0i = a[3] - a[18]; + x1r = wk3r * x0r - wk3i * x0i; + x1i = wk3r * x0i + wk3i * x0r; + x0r = a[10] + a[27]; + x0i = a[11] - a[26]; + x2r = wk1r * x0r + wk1i * x0i; + x2i = wk1r * x0i - wk1i * x0r; + y9r = x1r - x2r; + y9i = x1i - x2i; + y13r = x1r + x2r; + y13i = x1i + x2i; + x0r = a[4] - a[21]; + x0i = a[5] + a[20]; + x1r = wk2r * x0r - wk2i * x0i; + x1i = wk2r * x0i + wk2i * x0r; + x0r = a[12] - a[29]; + x0i = a[13] + a[28]; + x2r = wk2i * x0r - wk2r * x0i; + x2i = wk2i * x0i + wk2r * x0r; + y2r = x1r + x2r; + y2i = x1i + x2i; + y6r = x1r - x2r; + y6i = x1i - x2i; + x0r = a[4] + a[21]; + x0i = a[5] - a[20]; + x1r = wk2i * x0r - wk2r * x0i; + x1i = wk2i * x0i + wk2r * x0r; + x0r = a[12] + a[29]; + x0i = a[13] - a[28]; + x2r = wk2r * x0r - wk2i * x0i; + x2i = wk2r * x0i + wk2i * x0r; + y10r = x1r - x2r; + y10i = x1i - x2i; + y14r = x1r + x2r; + y14i = x1i + x2i; + x0r = a[6] - a[23]; + x0i = a[7] + a[22]; + x1r = wk3r * x0r - wk3i * x0i; + x1i = wk3r * x0i + wk3i * x0r; + x0r = a[14] - a[31]; + x0i = a[15] + a[30]; + x2r = wk1i * x0r - wk1r * x0i; + x2i = wk1i * x0i + wk1r * x0r; + y3r = x1r + x2r; + y3i = x1i + x2i; + y7r = x1r - x2r; + y7i = x1i - x2i; + x0r = a[6] + a[23]; + x0i = a[7] - a[22]; + x1r = wk1i * x0r + wk1r * x0i; + x1i = wk1i * x0i - wk1r * x0r; + x0r = a[14] + a[31]; + x0i = a[15] - a[30]; + x2r = wk3i * x0r - wk3r * x0i; + x2i = wk3i * x0i + wk3r * x0r; + y11r = x1r + x2r; + y11i = x1i + x2i; + y15r = x1r - x2r; + y15i = x1i - x2i; + x1r = y0r + y2r; + x1i = y0i + y2i; + x2r = y1r + y3r; + x2i = y1i + y3i; + a[0] = x1r + x2r; + a[1] = x1i + x2i; + a[2] = x1r - x2r; + a[3] = x1i - x2i; + x1r = y0r - y2r; + x1i = y0i - y2i; + x2r = y1r - y3r; + x2i = y1i - y3i; + a[4] = x1r - x2i; + a[5] = x1i + x2r; + a[6] = x1r + x2i; + a[7] = x1i - x2r; + x1r = y4r - y6i; + x1i = y4i + y6r; + x0r = y5r - y7i; + x0i = y5i + y7r; + x2r = wn4r * (x0r - x0i); + x2i = wn4r * (x0i + x0r); + a[8] = x1r + x2r; + a[9] = x1i + x2i; + a[10] = x1r - x2r; + a[11] = x1i - x2i; + x1r = y4r + y6i; + x1i = y4i - y6r; + x0r = y5r + y7i; + x0i = y5i - y7r; + x2r = wn4r * (x0r - x0i); + x2i = wn4r * (x0i + x0r); + a[12] = x1r - x2i; + a[13] = x1i + x2r; + a[14] = x1r + x2i; + a[15] = x1i - x2r; + x1r = y8r + y10r; + x1i = y8i + y10i; + x2r = y9r - y11r; + x2i = y9i - y11i; + a[16] = x1r + x2r; + a[17] = x1i + x2i; + a[18] = x1r - x2r; + a[19] = x1i - x2i; + x1r = y8r - y10r; + x1i = y8i - y10i; + x2r = y9r + y11r; + x2i = y9i + y11i; + a[20] = x1r - x2i; + a[21] = x1i + x2r; + a[22] = x1r + x2i; + a[23] = x1i - x2r; + x1r = y12r - y14i; + x1i = y12i + y14r; + x0r = y13r + y15i; + x0i = y13i - y15r; + x2r = wn4r * (x0r - x0i); + x2i = wn4r * (x0i + x0r); + a[24] = x1r + x2r; + a[25] = x1i + x2i; + a[26] = x1r - x2r; + a[27] = x1i - x2i; + x1r = y12r + y14i; + x1i = y12i - y14r; + x0r = y13r - y15i; + x0i = y13i + y15r; + x2r = wn4r * (x0r - x0i); + x2i = wn4r * (x0i + x0r); + a[28] = x1r - x2i; + a[29] = x1i + x2r; + a[30] = x1r + x2i; + a[31] = x1i - x2r; +} + + +void cftf081(FFTFLT *a, FFTFLT *w) +{ + FFTFLT wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, + y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; + + wn4r = w[1]; + x0r = a[0] + a[8]; + x0i = a[1] + a[9]; + x1r = a[0] - a[8]; + x1i = a[1] - a[9]; + x2r = a[4] + a[12]; + x2i = a[5] + a[13]; + x3r = a[4] - a[12]; + x3i = a[5] - a[13]; + y0r = x0r + x2r; + y0i = x0i + x2i; + y2r = x0r - x2r; + y2i = x0i - x2i; + y1r = x1r - x3i; + y1i = x1i + x3r; + y3r = x1r + x3i; + y3i = x1i - x3r; + x0r = a[2] + a[10]; + x0i = a[3] + a[11]; + x1r = a[2] - a[10]; + x1i = a[3] - a[11]; + x2r = a[6] + a[14]; + x2i = a[7] + a[15]; + x3r = a[6] - a[14]; + x3i = a[7] - a[15]; + y4r = x0r + x2r; + y4i = x0i + x2i; + y6r = x0r - x2r; + y6i = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + x2r = x1r + x3i; + x2i = x1i - x3r; + y5r = wn4r * (x0r - x0i); + y5i = wn4r * (x0r + x0i); + y7r = wn4r * (x2r - x2i); + y7i = wn4r * (x2r + x2i); + a[8] = y1r + y5r; + a[9] = y1i + y5i; + a[10] = y1r - y5r; + a[11] = y1i - y5i; + a[12] = y3r - y7i; + a[13] = y3i + y7r; + a[14] = y3r + y7i; + a[15] = y3i - y7r; + a[0] = y0r + y4r; + a[1] = y0i + y4i; + a[2] = y0r - y4r; + a[3] = y0i - y4i; + a[4] = y2r - y6i; + a[5] = y2i + y6r; + a[6] = y2r + y6i; + a[7] = y2i - y6r; +} + + +void cftf082(FFTFLT *a, FFTFLT *w) +{ + FFTFLT wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, + y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; + + wn4r = w[1]; + wk1r = w[2]; + wk1i = w[3]; + y0r = a[0] - a[9]; + y0i = a[1] + a[8]; + y1r = a[0] + a[9]; + y1i = a[1] - a[8]; + x0r = a[4] - a[13]; + x0i = a[5] + a[12]; + y2r = wn4r * (x0r - x0i); + y2i = wn4r * (x0i + x0r); + x0r = a[4] + a[13]; + x0i = a[5] - a[12]; + y3r = wn4r * (x0r - x0i); + y3i = wn4r * (x0i + x0r); + x0r = a[2] - a[11]; + x0i = a[3] + a[10]; + y4r = wk1r * x0r - wk1i * x0i; + y4i = wk1r * x0i + wk1i * x0r; + x0r = a[2] + a[11]; + x0i = a[3] - a[10]; + y5r = wk1i * x0r - wk1r * x0i; + y5i = wk1i * x0i + wk1r * x0r; + x0r = a[6] - a[15]; + x0i = a[7] + a[14]; + y6r = wk1i * x0r - wk1r * x0i; + y6i = wk1i * x0i + wk1r * x0r; + x0r = a[6] + a[15]; + x0i = a[7] - a[14]; + y7r = wk1r * x0r - wk1i * x0i; + y7i = wk1r * x0i + wk1i * x0r; + x0r = y0r + y2r; + x0i = y0i + y2i; + x1r = y4r + y6r; + x1i = y4i + y6i; + a[0] = x0r + x1r; + a[1] = x0i + x1i; + a[2] = x0r - x1r; + a[3] = x0i - x1i; + x0r = y0r - y2r; + x0i = y0i - y2i; + x1r = y4r - y6r; + x1i = y4i - y6i; + a[4] = x0r - x1i; + a[5] = x0i + x1r; + a[6] = x0r + x1i; + a[7] = x0i - x1r; + x0r = y1r - y3i; + x0i = y1i + y3r; + x1r = y5r - y7r; + x1i = y5i - y7i; + a[8] = x0r + x1r; + a[9] = x0i + x1i; + a[10] = x0r - x1r; + a[11] = x0i - x1i; + x0r = y1r + y3i; + x0i = y1i - y3r; + x1r = y5r + y7r; + x1i = y5i + y7i; + a[12] = x0r - x1i; + a[13] = x0i + x1r; + a[14] = x0r + x1i; + a[15] = x0i - x1r; +} + + +void cftf040(FFTFLT *a) +{ + FFTFLT x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + x0r = a[0] + a[4]; + x0i = a[1] + a[5]; + x1r = a[0] - a[4]; + x1i = a[1] - a[5]; + x2r = a[2] + a[6]; + x2i = a[3] + a[7]; + x3r = a[2] - a[6]; + x3i = a[3] - a[7]; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[2] = x1r - x3i; + a[3] = x1i + x3r; + a[4] = x0r - x2r; + a[5] = x0i - x2i; + a[6] = x1r + x3i; + a[7] = x1i - x3r; +} + + +void cftb040(FFTFLT *a) +{ + FFTFLT x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + x0r = a[0] + a[4]; + x0i = a[1] + a[5]; + x1r = a[0] - a[4]; + x1i = a[1] - a[5]; + x2r = a[2] + a[6]; + x2i = a[3] + a[7]; + x3r = a[2] - a[6]; + x3i = a[3] - a[7]; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[2] = x1r + x3i; + a[3] = x1i - x3r; + a[4] = x0r - x2r; + a[5] = x0i - x2i; + a[6] = x1r - x3i; + a[7] = x1i + x3r; +} + + +void cftx020(FFTFLT *a) +{ + FFTFLT x0r, x0i; + + x0r = a[0] - a[2]; + x0i = a[1] - a[3]; + a[0] += a[2]; + a[1] += a[3]; + a[2] = x0r; + a[3] = x0i; +} + + +void rftfsub(int n, FFTFLT *a, int nc, FFTFLT *c) +{ + int j, k, kk, ks, m; + FFTFLT wkr, wki, xr, xi, yr, yi; + + m = n >> 1; + ks = 2 * nc / m; + kk = 0; + for (j = 2; j < m; j += 2) { + k = n - j; + kk += ks; + wkr = 0.5 - c[nc - kk]; + wki = c[kk]; + xr = a[j] - a[k]; + xi = a[j + 1] + a[k + 1]; + yr = wkr * xr - wki * xi; + yi = wkr * xi + wki * xr; + a[j] -= yr; + a[j + 1] -= yi; + a[k] += yr; + a[k + 1] -= yi; + } +} + + +void rftbsub(int n, FFTFLT *a, int nc, FFTFLT *c) +{ + int j, k, kk, ks, m; + FFTFLT wkr, wki, xr, xi, yr, yi; + + m = n >> 1; + ks = 2 * nc / m; + kk = 0; + for (j = 2; j < m; j += 2) { + k = n - j; + kk += ks; + wkr = 0.5 - c[nc - kk]; + wki = c[kk]; + xr = a[j] - a[k]; + xi = a[j + 1] + a[k + 1]; + yr = wkr * xr + wki * xi; + yi = wkr * xi - wki * xr; + a[j] -= yr; + a[j + 1] -= yi; + a[k] += yr; + a[k + 1] -= yi; + } +} + + +void dctsub(int n, FFTFLT *a, int nc, FFTFLT *c) +{ + int j, k, kk, ks, m; + FFTFLT wkr, wki, xr; + + m = n >> 1; + ks = nc / n; + kk = 0; + for (j = 1; j < m; j++) { + k = n - j; + kk += ks; + wkr = c[kk] - c[nc - kk]; + wki = c[kk] + c[nc - kk]; + xr = wki * a[j] - wkr * a[k]; + a[j] = wkr * a[j] + wki * a[k]; + a[k] = xr; + } + a[m] *= c[0]; +} + + +void dstsub(int n, FFTFLT *a, int nc, FFTFLT *c) +{ + int j, k, kk, ks, m; + FFTFLT wkr, wki, xr; + + m = n >> 1; + ks = nc / n; + kk = 0; + for (j = 1; j < m; j++) { + k = n - j; + kk += ks; + wkr = c[kk] - c[nc - kk]; + wki = c[kk] + c[nc - kk]; + xr = wki * a[k] - wkr * a[j]; + a[k] = wkr * a[k] + wki * a[j]; + a[j] = xr; + } + a[m] *= c[0]; +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/d_fft_fftw.c b/ports/camomile/source/LibPd/pure-data/src/d_fft_fftw.c new file mode 100644 index 00000000..2e341636 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_fft_fftw.c @@ -0,0 +1,185 @@ +/* Copyright (c) 1997- Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* --------- Pd interface to FFTW library; imitate Mayer API ---------- */ + +/* changes and additions for FFTW3 by Thomas Grill */ + +#include "m_pd.h" +#include + +int ilog2(int n); + +#define MINFFT 0 +#define MAXFFT 30 + +/* from the FFTW website: + #include + ... + { + fftw_complex *in, *out; + fftw_plan p; + ... + in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N); + out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N); + p = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE); + ... + fftw_execute(p); + ... + fftw_destroy_plan(p); + fftw_free(in); fftw_free(out); + } + +FFTW_FORWARD or FFTW_BACKWARD, and indicates the direction of the transform you +are interested in. Alternatively, you can use the sign of the exponent in the +transform, -1 or +1, which corresponds to FFTW_FORWARD or FFTW_BACKWARD +respectively. The flags argument is either FFTW_MEASURE + +*/ + +/* complex stuff */ + +typedef struct { + fftwf_plan plan; + fftwf_complex *in,*out; +} cfftw_info; + +static cfftw_info cfftw_fwd[MAXFFT+1 - MINFFT],cfftw_bwd[MAXFFT+1 - MINFFT]; + +static cfftw_info *cfftw_getplan(int n,int fwd) +{ + cfftw_info *info; + int logn = ilog2(n); + if (logn < MINFFT || logn > MAXFFT) + return (0); + info = (fwd?cfftw_fwd:cfftw_bwd)+(logn-MINFFT); + if (!info->plan) + { + pd_globallock(); + if (!info->plan) /* recheck in case it got set while we waited */ + { + info->in = + (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * n); + info->out = + (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * n); + info->plan = fftwf_plan_dft_1d(n, info->in, info->out, + fwd?FFTW_FORWARD:FFTW_BACKWARD, FFTW_MEASURE); + } + pd_globalunlock(); + } + return info; +} + + +/* real stuff */ + +typedef struct { + fftwf_plan plan; + float *in,*out; +} rfftw_info; + +static rfftw_info rfftw_fwd[MAXFFT+1 - MINFFT],rfftw_bwd[MAXFFT+1 - MINFFT]; + +static rfftw_info *rfftw_getplan(int n,int fwd) +{ + rfftw_info *info; + int logn = ilog2(n); + if (logn < MINFFT || logn > MAXFFT) + return (0); + info = (fwd?rfftw_fwd:rfftw_bwd)+(logn-MINFFT); + if (!info->plan) + { + info->in = (float*) fftwf_malloc(sizeof(float) * n); + info->out = (float*) fftwf_malloc(sizeof(float) * n); + info->plan = fftwf_plan_r2r_1d(n, info->in, info->out, fwd?FFTW_R2HC:FFTW_HC2R, FFTW_MEASURE); + } + return info; +} + + + +EXTERN void mayer_fht(float *fz, int n) +{ + post("FHT: not yet implemented"); +} + +static void mayer_do_cfft(int n, float *fz1, float *fz2, int fwd) +{ + int i; + float *fz; + cfftw_info *p = cfftw_getplan(n, fwd); + if (!p) + return; + + for (i = 0, fz = (float *)p->in; i < n; i++) + fz[i*2] = fz1[i], fz[i*2+1] = fz2[i]; + + fftwf_execute(p->plan); + + for (i = 0, fz = (float *)p->out; i < n; i++) + fz1[i] = fz[i*2], fz2[i] = fz[i*2+1]; +} + +EXTERN void mayer_fft(int n, float *fz1, float *fz2) +{ + mayer_do_cfft(n, fz1, fz2, 1); +} + +EXTERN void mayer_ifft(int n, float *fz1, float *fz2) +{ + mayer_do_cfft(n, fz1, fz2, 0); +} + +/* + in the following the sign flips are done to + be compatible with the mayer_fft implementation, + but it's probably the mayer_fft that should be corrected... +*/ + +EXTERN void mayer_realfft(int n, float *fz) +{ + int i; + rfftw_info *p = rfftw_getplan(n, 1); + if (!p) + return; + + for (i = 0; i < n; i++) + p->in[i] = fz[i]; + fftwf_execute(p->plan); + for (i = 0; i < n/2+1; i++) + fz[i] = p->out[i]; + for (; i < n; i++) + fz[i] = -p->out[i]; +} + +EXTERN void mayer_realifft(int n, float *fz) +{ + int i; + rfftw_info *p = rfftw_getplan(n, 0); + if (!p) + return; + + for (i = 0; i < n/2+1; i++) + p->in[i] = fz[i]; + for (; i < n; i++) + p->in[i] = -fz[i]; + fftwf_execute(p->plan); + for (i = 0; i < n; i++) + fz[i] = p->out[i]; +} + + /* ancient ISPW-like version, used in fiddle~ and perhaps other externs + here and there. */ +void pd_fft(t_float *buf, int npoints, int inverse) +{ + cfftw_info *p = cfftw_getplan(npoints, !inverse); + int i; + float *fz; + for (i = 0, fz = (float *)(p->in); i < 2 * npoints; i++) + *fz++ = buf[i]; + fftwf_execute(p->plan); + for (i = 0, fz = (float *)(p->out); i < 2 * npoints; i++) + buf[i] = *fz++; +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/d_filter.c b/ports/camomile/source/LibPd/pure-data/src/d_filter.c new file mode 100644 index 00000000..c3ea6dff --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_filter.c @@ -0,0 +1,1082 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* "filters", both linear and nonlinear. +*/ +#include "m_pd.h" +#include + +/* ---------------- hip~ - 1-pole 1-zero hipass filter. ----------------- */ + +typedef struct hipctl +{ + t_sample c_x; + t_sample c_coef; +} t_hipctl; + +typedef struct sighip +{ + t_object x_obj; + t_float x_sr; + t_float x_hz; + t_hipctl x_cspace; + t_hipctl *x_ctl; + t_float x_f; +} t_sighip; + +t_class *sighip_class; +static void sighip_ft1(t_sighip *x, t_floatarg f); + +static void *sighip_new(t_floatarg f) +{ + t_sighip *x = (t_sighip *)pd_new(sighip_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1")); + outlet_new(&x->x_obj, &s_signal); + x->x_sr = 44100; + x->x_ctl = &x->x_cspace; + x->x_cspace.c_x = 0; + sighip_ft1(x, f); + x->x_f = 0; + return (x); +} + +static void sighip_ft1(t_sighip *x, t_floatarg f) +{ + if (f < 0) f = 0; + x->x_hz = f; + x->x_ctl->c_coef = 1 - f * (2 * 3.14159) / x->x_sr; + if (x->x_ctl->c_coef < 0) + x->x_ctl->c_coef = 0; + else if (x->x_ctl->c_coef > 1) + x->x_ctl->c_coef = 1; +} + +static t_int *sighip_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + t_hipctl *c = (t_hipctl *)(w[3]); + int n = (int)w[4]; + int i; + t_sample last = c->c_x; + t_sample coef = c->c_coef; + if (coef < 1) + { + t_sample normal = 0.5*(1+coef); + for (i = 0; i < n; i++) + { + t_sample new = *in++ + coef * last; + *out++ = normal * (new - last); + last = new; + } + if (PD_BIGORSMALL(last)) + last = 0; + c->c_x = last; + } + else + { + for (i = 0; i < n; i++) + *out++ = *in++; + c->c_x = 0; + } + return (w+5); +} + +static t_int *sighip_perform_old(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + t_hipctl *c = (t_hipctl *)(w[3]); + int n = (int)w[4]; + int i; + t_sample last = c->c_x; + t_sample coef = c->c_coef; + if (coef < 1) + { + for (i = 0; i < n; i++) + { + t_sample new = *in++ + coef * last; + *out++ = new - last; + last = new; + } + if (PD_BIGORSMALL(last)) + last = 0; + c->c_x = last; + } + else + { + for (i = 0; i < n; i++) + *out++ = *in++; + c->c_x = 0; + } + return (w+5); +} + +static void sighip_dsp(t_sighip *x, t_signal **sp) +{ + x->x_sr = sp[0]->s_sr; + sighip_ft1(x, x->x_hz); + dsp_add((pd_compatibilitylevel > 43 ? + sighip_perform : sighip_perform_old), + 4, sp[0]->s_vec, sp[1]->s_vec, x->x_ctl, sp[0]->s_n); +} + +static void sighip_clear(t_sighip *x, t_floatarg q) +{ + x->x_cspace.c_x = 0; +} + +void sighip_setup(void) +{ + sighip_class = class_new(gensym("hip~"), (t_newmethod)sighip_new, 0, + sizeof(t_sighip), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(sighip_class, t_sighip, x_f); + class_addmethod(sighip_class, (t_method)sighip_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(sighip_class, (t_method)sighip_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(sighip_class, (t_method)sighip_clear, gensym("clear"), 0); +} + +/* ---------------- lop~ - 1-pole lopass filter. ----------------- */ + +typedef struct lopctl +{ + t_sample c_x; + t_sample c_coef; +} t_lopctl; + +typedef struct siglop +{ + t_object x_obj; + t_float x_sr; + t_float x_hz; + t_lopctl x_cspace; + t_lopctl *x_ctl; + t_float x_f; +} t_siglop; + +t_class *siglop_class; + +static void siglop_ft1(t_siglop *x, t_floatarg f); + +static void *siglop_new(t_floatarg f) +{ + t_siglop *x = (t_siglop *)pd_new(siglop_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1")); + outlet_new(&x->x_obj, &s_signal); + x->x_sr = 44100; + x->x_ctl = &x->x_cspace; + x->x_cspace.c_x = 0; + siglop_ft1(x, f); + x->x_f = 0; + return (x); +} + +static void siglop_ft1(t_siglop *x, t_floatarg f) +{ + if (f < 0) f = 0; + x->x_hz = f; + x->x_ctl->c_coef = f * (2 * 3.14159) / x->x_sr; + if (x->x_ctl->c_coef > 1) + x->x_ctl->c_coef = 1; + else if (x->x_ctl->c_coef < 0) + x->x_ctl->c_coef = 0; +} + +static void siglop_clear(t_siglop *x, t_floatarg q) +{ + x->x_cspace.c_x = 0; +} + +static t_int *siglop_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + t_lopctl *c = (t_lopctl *)(w[3]); + int n = (int)w[4]; + int i; + t_sample last = c->c_x; + t_sample coef = c->c_coef; + t_sample feedback = 1 - coef; + for (i = 0; i < n; i++) + last = *out++ = coef * *in++ + feedback * last; + if (PD_BIGORSMALL(last)) + last = 0; + c->c_x = last; + return (w+5); +} + +static void siglop_dsp(t_siglop *x, t_signal **sp) +{ + x->x_sr = sp[0]->s_sr; + siglop_ft1(x, x->x_hz); + dsp_add(siglop_perform, 4, + sp[0]->s_vec, sp[1]->s_vec, + x->x_ctl, sp[0]->s_n); + +} + +void siglop_setup(void) +{ + siglop_class = class_new(gensym("lop~"), (t_newmethod)siglop_new, 0, + sizeof(t_siglop), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(siglop_class, t_siglop, x_f); + class_addmethod(siglop_class, (t_method)siglop_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(siglop_class, (t_method)siglop_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(siglop_class, (t_method)siglop_clear, gensym("clear"), 0); +} + +/* ---------------- bp~ - 2-pole bandpass filter. ----------------- */ + +typedef struct bpctl +{ + t_sample c_x1; + t_sample c_x2; + t_sample c_coef1; + t_sample c_coef2; + t_sample c_gain; +} t_bpctl; + +typedef struct sigbp +{ + t_object x_obj; + t_float x_sr; + t_float x_freq; + t_float x_q; + t_bpctl x_cspace; + t_bpctl *x_ctl; + t_float x_f; +} t_sigbp; + +t_class *sigbp_class; + +static void sigbp_docoef(t_sigbp *x, t_floatarg f, t_floatarg q); + +static void *sigbp_new(t_floatarg f, t_floatarg q) +{ + t_sigbp *x = (t_sigbp *)pd_new(sigbp_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft2")); + outlet_new(&x->x_obj, &s_signal); + x->x_sr = 44100; + x->x_ctl = &x->x_cspace; + x->x_cspace.c_x1 = 0; + x->x_cspace.c_x2 = 0; + sigbp_docoef(x, f, q); + x->x_f = 0; + return (x); +} + +static t_float sigbp_qcos(t_float f) +{ + if (f >= -(0.5f*3.14159f) && f <= 0.5f*3.14159f) + { + t_float g = f*f; + return (((g*g*g * (-1.0f/720.0f) + g*g*(1.0f/24.0f)) - g*0.5) + 1); + } + else return (0); +} + +static void sigbp_docoef(t_sigbp *x, t_floatarg f, t_floatarg q) +{ + t_float r, oneminusr, omega; + if (f < 0.001) f = 10; + if (q < 0) q = 0; + x->x_freq = f; + x->x_q = q; + omega = f * (2.0f * 3.14159f) / x->x_sr; + if (q < 0.001) oneminusr = 1.0f; + else oneminusr = omega/q; + if (oneminusr > 1.0f) oneminusr = 1.0f; + r = 1.0f - oneminusr; + x->x_ctl->c_coef1 = 2.0f * sigbp_qcos(omega) * r; + x->x_ctl->c_coef2 = - r * r; + x->x_ctl->c_gain = 2 * oneminusr * (oneminusr + r * omega); + /* post("r %f, omega %f, coef1 %f, coef2 %f", + r, omega, x->x_ctl->c_coef1, x->x_ctl->c_coef2); */ +} + +static void sigbp_ft1(t_sigbp *x, t_floatarg f) +{ + sigbp_docoef(x, f, x->x_q); +} + +static void sigbp_ft2(t_sigbp *x, t_floatarg q) +{ + sigbp_docoef(x, x->x_freq, q); +} + +static void sigbp_clear(t_sigbp *x, t_floatarg q) +{ + x->x_ctl->c_x1 = x->x_ctl->c_x2 = 0; +} + +static t_int *sigbp_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + t_bpctl *c = (t_bpctl *)(w[3]); + int n = (int)w[4]; + int i; + t_sample last = c->c_x1; + t_sample prev = c->c_x2; + t_sample coef1 = c->c_coef1; + t_sample coef2 = c->c_coef2; + t_sample gain = c->c_gain; + for (i = 0; i < n; i++) + { + t_sample output = *in++ + coef1 * last + coef2 * prev; + *out++ = gain * output; + prev = last; + last = output; + } + if (PD_BIGORSMALL(last)) + last = 0; + if (PD_BIGORSMALL(prev)) + prev = 0; + c->c_x1 = last; + c->c_x2 = prev; + return (w+5); +} + +static void sigbp_dsp(t_sigbp *x, t_signal **sp) +{ + x->x_sr = sp[0]->s_sr; + sigbp_docoef(x, x->x_freq, x->x_q); + dsp_add(sigbp_perform, 4, + sp[0]->s_vec, sp[1]->s_vec, + x->x_ctl, sp[0]->s_n); + +} + +void sigbp_setup(void) +{ + sigbp_class = class_new(gensym("bp~"), (t_newmethod)sigbp_new, 0, + sizeof(t_sigbp), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(sigbp_class, t_sigbp, x_f); + class_addmethod(sigbp_class, (t_method)sigbp_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(sigbp_class, (t_method)sigbp_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(sigbp_class, (t_method)sigbp_ft2, + gensym("ft2"), A_FLOAT, 0); + class_addmethod(sigbp_class, (t_method)sigbp_clear, gensym("clear"), 0); +} + +/* ---------------- biquad~ - raw biquad filter ----------------- */ + +typedef struct biquadctl +{ + t_sample c_x1; + t_sample c_x2; + t_sample c_fb1; + t_sample c_fb2; + t_sample c_ff1; + t_sample c_ff2; + t_sample c_ff3; +} t_biquadctl; + +typedef struct sigbiquad +{ + t_object x_obj; + t_float x_f; + t_biquadctl x_cspace; + t_biquadctl *x_ctl; +} t_sigbiquad; + +t_class *sigbiquad_class; + +static void sigbiquad_list(t_sigbiquad *x, t_symbol *s, int argc, t_atom *argv); + +static void *sigbiquad_new(t_symbol *s, int argc, t_atom *argv) +{ + t_sigbiquad *x = (t_sigbiquad *)pd_new(sigbiquad_class); + outlet_new(&x->x_obj, &s_signal); + x->x_ctl = &x->x_cspace; + x->x_cspace.c_x1 = x->x_cspace.c_x2 = 0; + sigbiquad_list(x, s, argc, argv); + x->x_f = 0; + return (x); +} + +static t_int *sigbiquad_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + t_biquadctl *c = (t_biquadctl *)(w[3]); + int n = (int)w[4]; + int i; + t_sample last = c->c_x1; + t_sample prev = c->c_x2; + t_sample fb1 = c->c_fb1; + t_sample fb2 = c->c_fb2; + t_sample ff1 = c->c_ff1; + t_sample ff2 = c->c_ff2; + t_sample ff3 = c->c_ff3; + for (i = 0; i < n; i++) + { + t_sample output = *in++ + fb1 * last + fb2 * prev; + if (PD_BIGORSMALL(output)) + output = 0; + *out++ = ff1 * output + ff2 * last + ff3 * prev; + prev = last; + last = output; + } + c->c_x1 = last; + c->c_x2 = prev; + return (w+5); +} + +static void sigbiquad_list(t_sigbiquad *x, t_symbol *s, int argc, t_atom *argv) +{ + t_float fb1 = atom_getfloatarg(0, argc, argv); + t_float fb2 = atom_getfloatarg(1, argc, argv); + t_float ff1 = atom_getfloatarg(2, argc, argv); + t_float ff2 = atom_getfloatarg(3, argc, argv); + t_float ff3 = atom_getfloatarg(4, argc, argv); + t_float discriminant = fb1 * fb1 + 4 * fb2; + t_biquadctl *c = x->x_ctl; + if (discriminant < 0) /* imaginary roots -- resonant filter */ + { + /* they're conjugates so we just check that the product + is less than one */ + if (fb2 >= -1.0f) goto stable; + } + else /* real roots */ + { + /* check that the parabola 1 - fb1 x - fb2 x^2 has a + vertex between -1 and 1, and that it's nonnegative + at both ends, which implies both roots are in [1-,1]. */ + if (fb1 <= 2.0f && fb1 >= -2.0f && + 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0) + goto stable; + } + /* if unstable, just bash to zero */ + fb1 = fb2 = ff1 = ff2 = ff3 = 0; +stable: + c->c_fb1 = fb1; + c->c_fb2 = fb2; + c->c_ff1 = ff1; + c->c_ff2 = ff2; + c->c_ff3 = ff3; +} + +static void sigbiquad_set(t_sigbiquad *x, t_symbol *s, int argc, t_atom *argv) +{ + t_biquadctl *c = x->x_ctl; + c->c_x1 = atom_getfloatarg(0, argc, argv); + c->c_x2 = atom_getfloatarg(1, argc, argv); +} + +static void sigbiquad_dsp(t_sigbiquad *x, t_signal **sp) +{ + dsp_add(sigbiquad_perform, 4, + sp[0]->s_vec, sp[1]->s_vec, + x->x_ctl, sp[0]->s_n); + +} + +void sigbiquad_setup(void) +{ + sigbiquad_class = class_new(gensym("biquad~"), (t_newmethod)sigbiquad_new, + 0, sizeof(t_sigbiquad), 0, A_GIMME, 0); + CLASS_MAINSIGNALIN(sigbiquad_class, t_sigbiquad, x_f); + class_addmethod(sigbiquad_class, (t_method)sigbiquad_dsp, + gensym("dsp"), A_CANT, 0); + class_addlist(sigbiquad_class, sigbiquad_list); + class_addmethod(sigbiquad_class, (t_method)sigbiquad_set, gensym("set"), + A_GIMME, 0); + class_addmethod(sigbiquad_class, (t_method)sigbiquad_set, gensym("clear"), + A_GIMME, 0); +} + +/* ---------------- samphold~ - sample and hold ----------------- */ + +typedef struct sigsamphold +{ + t_object x_obj; + t_float x_f; + t_sample x_lastin; + t_sample x_lastout; +} t_sigsamphold; + +t_class *sigsamphold_class; + +static void *sigsamphold_new(void) +{ + t_sigsamphold *x = (t_sigsamphold *)pd_new(sigsamphold_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_lastin = 0; + x->x_lastout = 0; + x->x_f = 0; + return (x); +} + +static t_int *sigsamphold_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + t_sigsamphold *x = (t_sigsamphold *)(w[4]); + int n = (int)w[5]; + int i; + t_sample lastin = x->x_lastin; + t_sample lastout = x->x_lastout; + for (i = 0; i < n; i++, in1++) + { + t_sample next = *in2++; + if (next < lastin) lastout = *in1; + *out++ = lastout; + lastin = next; + } + x->x_lastin = lastin; + x->x_lastout = lastout; + return (w+6); +} + +static void sigsamphold_dsp(t_sigsamphold *x, t_signal **sp) +{ + dsp_add(sigsamphold_perform, 5, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, + x, sp[0]->s_n); +} + +static void sigsamphold_reset(t_sigsamphold *x, t_symbol *s, int argc, + t_atom *argv) +{ + x->x_lastin = ((argc > 0 && (argv[0].a_type == A_FLOAT)) ? + argv[0].a_w.w_float : 1e20); +} + +static void sigsamphold_set(t_sigsamphold *x, t_float f) +{ + x->x_lastout = f; +} + +void sigsamphold_setup(void) +{ + sigsamphold_class = class_new(gensym("samphold~"), + (t_newmethod)sigsamphold_new, 0, sizeof(t_sigsamphold), 0, 0); + CLASS_MAINSIGNALIN(sigsamphold_class, t_sigsamphold, x_f); + class_addmethod(sigsamphold_class, (t_method)sigsamphold_set, + gensym("set"), A_DEFFLOAT, 0); + class_addmethod(sigsamphold_class, (t_method)sigsamphold_reset, + gensym("reset"), A_GIMME, 0); + class_addmethod(sigsamphold_class, (t_method)sigsamphold_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ---------------- rpole~ - real one-pole filter (raw) ----------------- */ + +typedef struct sigrpole +{ + t_object x_obj; + t_float x_f; + t_sample x_last; +} t_sigrpole; + +t_class *sigrpole_class; + +static void *sigrpole_new(t_float f) +{ + t_sigrpole *x = (t_sigrpole *)pd_new(sigrpole_class); + pd_float( + (t_pd *)inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal), + f); + outlet_new(&x->x_obj, &s_signal); + x->x_last = 0; + return (x); +} + +static t_int *sigrpole_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + t_sigrpole *x = (t_sigrpole *)(w[4]); + int n = (int)w[5]; + int i; + t_sample last = x->x_last; + for (i = 0; i < n; i++) + { + t_sample next = *in1++; + t_sample coef = *in2++; + *out++ = last = coef * last + next; + } + if (PD_BIGORSMALL(last)) + last = 0; + x->x_last = last; + return (w+6); +} + +static void sigrpole_dsp(t_sigrpole *x, t_signal **sp) +{ + dsp_add(sigrpole_perform, 5, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, + x, sp[0]->s_n); +} + +static void sigrpole_clear(t_sigrpole *x) +{ + x->x_last = 0; +} + +static void sigrpole_set(t_sigrpole *x, t_float f) +{ + x->x_last = f; +} + +void sigrpole_setup(void) +{ + sigrpole_class = class_new(gensym("rpole~"), + (t_newmethod)sigrpole_new, 0, sizeof(t_sigrpole), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(sigrpole_class, t_sigrpole, x_f); + class_addmethod(sigrpole_class, (t_method)sigrpole_set, + gensym("set"), A_DEFFLOAT, 0); + class_addmethod(sigrpole_class, (t_method)sigrpole_clear, + gensym("clear"), 0); + class_addmethod(sigrpole_class, (t_method)sigrpole_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ---------------- rzero~ - real one-zero filter (raw) ----------------- */ + +typedef struct sigrzero +{ + t_object x_obj; + t_float x_f; + t_sample x_last; +} t_sigrzero; + +t_class *sigrzero_class; + +static void *sigrzero_new(t_float f) +{ + t_sigrzero *x = (t_sigrzero *)pd_new(sigrzero_class); + pd_float( + (t_pd *)inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal), + f); + outlet_new(&x->x_obj, &s_signal); + x->x_last = 0; + return (x); +} + +static t_int *sigrzero_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + t_sigrzero *x = (t_sigrzero *)(w[4]); + int n = (int)w[5]; + int i; + t_sample last = x->x_last; + for (i = 0; i < n; i++) + { + t_sample next = *in1++; + t_sample coef = *in2++; + *out++ = next - coef * last; + last = next; + } + x->x_last = last; + return (w+6); +} + +static void sigrzero_dsp(t_sigrzero *x, t_signal **sp) +{ + dsp_add(sigrzero_perform, 5, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, + x, sp[0]->s_n); +} + +static void sigrzero_clear(t_sigrzero *x) +{ + x->x_last = 0; +} + +static void sigrzero_set(t_sigrzero *x, t_float f) +{ + x->x_last = f; +} + +void sigrzero_setup(void) +{ + sigrzero_class = class_new(gensym("rzero~"), + (t_newmethod)sigrzero_new, 0, sizeof(t_sigrzero), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(sigrzero_class, t_sigrzero, x_f); + class_addmethod(sigrzero_class, (t_method)sigrzero_set, + gensym("set"), A_DEFFLOAT, 0); + class_addmethod(sigrzero_class, (t_method)sigrzero_clear, + gensym("clear"), 0); + class_addmethod(sigrzero_class, (t_method)sigrzero_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ---------- rzero_rev~ - real, reverse one-zero filter (raw) ------------ */ + +typedef struct sigrzero_rev +{ + t_object x_obj; + t_float x_f; + t_sample x_last; +} t_sigrzero_rev; + +t_class *sigrzero_rev_class; + +static void *sigrzero_rev_new(t_float f) +{ + t_sigrzero_rev *x = (t_sigrzero_rev *)pd_new(sigrzero_rev_class); + pd_float( + (t_pd *)inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal), + f); + outlet_new(&x->x_obj, &s_signal); + x->x_last = 0; + return (x); +} + +static t_int *sigrzero_rev_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + t_sigrzero_rev *x = (t_sigrzero_rev *)(w[4]); + int n = (int)w[5]; + int i; + t_sample last = x->x_last; + for (i = 0; i < n; i++) + { + t_sample next = *in1++; + t_sample coef = *in2++; + *out++ = last - coef * next; + last = next; + } + x->x_last = last; + return (w+6); +} + +static void sigrzero_rev_dsp(t_sigrzero_rev *x, t_signal **sp) +{ + dsp_add(sigrzero_rev_perform, 5, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, + x, sp[0]->s_n); +} + +static void sigrzero_rev_clear(t_sigrzero_rev *x) +{ + x->x_last = 0; +} + +static void sigrzero_rev_set(t_sigrzero_rev *x, t_float f) +{ + x->x_last = f; +} + +void sigrzero_rev_setup(void) +{ + sigrzero_rev_class = class_new(gensym("rzero_rev~"), + (t_newmethod)sigrzero_rev_new, 0, sizeof(t_sigrzero_rev), + 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(sigrzero_rev_class, t_sigrzero_rev, x_f); + class_addmethod(sigrzero_rev_class, (t_method)sigrzero_rev_set, + gensym("set"), A_DEFFLOAT, 0); + class_addmethod(sigrzero_rev_class, (t_method)sigrzero_rev_clear, + gensym("clear"), 0); + class_addmethod(sigrzero_rev_class, (t_method)sigrzero_rev_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* -------------- cpole~ - complex one-pole filter (raw) --------------- */ + +typedef struct sigcpole +{ + t_object x_obj; + t_float x_f; + t_sample x_lastre; + t_sample x_lastim; +} t_sigcpole; + +t_class *sigcpole_class; + +static void *sigcpole_new(t_float re, t_float im) +{ + t_sigcpole *x = (t_sigcpole *)pd_new(sigcpole_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + pd_float( + (t_pd *)inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal), + re); + pd_float( + (t_pd *)inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal), + im); + outlet_new(&x->x_obj, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_lastre = x->x_lastim = 0; + x->x_f = 0; + return (x); +} + +static t_int *sigcpole_perform(t_int *w) +{ + t_sample *inre1 = (t_sample *)(w[1]); + t_sample *inim1 = (t_sample *)(w[2]); + t_sample *inre2 = (t_sample *)(w[3]); + t_sample *inim2 = (t_sample *)(w[4]); + t_sample *outre = (t_sample *)(w[5]); + t_sample *outim = (t_sample *)(w[6]); + t_sigcpole *x = (t_sigcpole *)(w[7]); + int n = (int)w[8]; + int i; + t_sample lastre = x->x_lastre; + t_sample lastim = x->x_lastim; + for (i = 0; i < n; i++) + { + t_sample nextre = *inre1++; + t_sample nextim = *inim1++; + t_sample coefre = *inre2++; + t_sample coefim = *inim2++; + t_sample tempre = *outre++ = nextre + lastre * coefre - lastim * coefim; + lastim = *outim++ = nextim + lastre * coefim + lastim * coefre; + lastre = tempre; + } + if (PD_BIGORSMALL(lastre)) + lastre = 0; + if (PD_BIGORSMALL(lastim)) + lastim = 0; + x->x_lastre = lastre; + x->x_lastim = lastim; + return (w+9); +} + +static void sigcpole_dsp(t_sigcpole *x, t_signal **sp) +{ + dsp_add(sigcpole_perform, 8, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, + sp[4]->s_vec, sp[5]->s_vec, x, sp[0]->s_n); +} + +static void sigcpole_clear(t_sigcpole *x) +{ + x->x_lastre = x->x_lastim = 0; +} + +static void sigcpole_set(t_sigcpole *x, t_float re, t_float im) +{ + x->x_lastre = re; + x->x_lastim = im; +} + +void sigcpole_setup(void) +{ + sigcpole_class = class_new(gensym("cpole~"), + (t_newmethod)sigcpole_new, 0, sizeof(t_sigcpole), 0, + A_DEFFLOAT, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(sigcpole_class, t_sigcpole, x_f); + class_addmethod(sigcpole_class, (t_method)sigcpole_set, + gensym("set"), A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(sigcpole_class, (t_method)sigcpole_clear, + gensym("clear"), 0); + class_addmethod(sigcpole_class, (t_method)sigcpole_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* -------------- czero~ - complex one-zero filter (raw) --------------- */ + +typedef struct sigczero +{ + t_object x_obj; + t_float x_f; + t_sample x_lastre; + t_sample x_lastim; +} t_sigczero; + +t_class *sigczero_class; + +static void *sigczero_new(t_float re, t_float im) +{ + t_sigczero *x = (t_sigczero *)pd_new(sigczero_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + pd_float( + (t_pd *)inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal), + re); + pd_float( + (t_pd *)inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal), + im); + outlet_new(&x->x_obj, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_lastre = x->x_lastim = 0; + x->x_f = 0; + return (x); +} + +static t_int *sigczero_perform(t_int *w) +{ + t_sample *inre1 = (t_sample *)(w[1]); + t_sample *inim1 = (t_sample *)(w[2]); + t_sample *inre2 = (t_sample *)(w[3]); + t_sample *inim2 = (t_sample *)(w[4]); + t_sample *outre = (t_sample *)(w[5]); + t_sample *outim = (t_sample *)(w[6]); + t_sigczero *x = (t_sigczero *)(w[7]); + int n = (int)w[8]; + int i; + t_sample lastre = x->x_lastre; + t_sample lastim = x->x_lastim; + for (i = 0; i < n; i++) + { + t_sample nextre = *inre1++; + t_sample nextim = *inim1++; + t_sample coefre = *inre2++; + t_sample coefim = *inim2++; + *outre++ = nextre - lastre * coefre + lastim * coefim; + *outim++ = nextim - lastre * coefim - lastim * coefre; + lastre = nextre; + lastim = nextim; + } + x->x_lastre = lastre; + x->x_lastim = lastim; + return (w+9); +} + +static void sigczero_dsp(t_sigczero *x, t_signal **sp) +{ + dsp_add(sigczero_perform, 8, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, + sp[4]->s_vec, sp[5]->s_vec, x, sp[0]->s_n); +} + +static void sigczero_clear(t_sigczero *x) +{ + x->x_lastre = x->x_lastim = 0; +} + +static void sigczero_set(t_sigczero *x, t_float re, t_float im) +{ + x->x_lastre = re; + x->x_lastim = im; +} + +void sigczero_setup(void) +{ + sigczero_class = class_new(gensym("czero~"), + (t_newmethod)sigczero_new, 0, sizeof(t_sigczero), 0, + A_DEFFLOAT, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(sigczero_class, t_sigczero, x_f); + class_addmethod(sigczero_class, (t_method)sigczero_set, + gensym("set"), A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(sigczero_class, (t_method)sigczero_clear, + gensym("clear"), 0); + class_addmethod(sigczero_class, (t_method)sigczero_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ------ czero_rev~ - complex one-zero filter (raw, reverse form) ----- */ + +typedef struct sigczero_rev +{ + t_object x_obj; + t_float x_f; + t_sample x_lastre; + t_sample x_lastim; +} t_sigczero_rev; + +t_class *sigczero_rev_class; + +static void *sigczero_rev_new(t_float re, t_float im) +{ + t_sigczero_rev *x = (t_sigczero_rev *)pd_new(sigczero_rev_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + pd_float( + (t_pd *)inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal), + re); + pd_float( + (t_pd *)inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal), + im); + outlet_new(&x->x_obj, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->x_lastre = x->x_lastim = 0; + x->x_f = 0; + return (x); +} + +static t_int *sigczero_rev_perform(t_int *w) +{ + t_sample *inre1 = (t_sample *)(w[1]); + t_sample *inim1 = (t_sample *)(w[2]); + t_sample *inre2 = (t_sample *)(w[3]); + t_sample *inim2 = (t_sample *)(w[4]); + t_sample *outre = (t_sample *)(w[5]); + t_sample *outim = (t_sample *)(w[6]); + t_sigczero_rev *x = (t_sigczero_rev *)(w[7]); + int n = (int)w[8]; + int i; + t_sample lastre = x->x_lastre; + t_sample lastim = x->x_lastim; + for (i = 0; i < n; i++) + { + t_sample nextre = *inre1++; + t_sample nextim = *inim1++; + t_sample coefre = *inre2++; + t_sample coefim = *inim2++; + /* transfer function is (A bar) - Z^-1, for the same + frequency response as 1 - AZ^-1 from czero_tilde. */ + *outre++ = lastre - nextre * coefre - nextim * coefim; + *outim++ = lastim - nextre * coefim + nextim * coefre; + lastre = nextre; + lastim = nextim; + } + x->x_lastre = lastre; + x->x_lastim = lastim; + return (w+9); +} + +static void sigczero_rev_dsp(t_sigczero_rev *x, t_signal **sp) +{ + dsp_add(sigczero_rev_perform, 8, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, + sp[4]->s_vec, sp[5]->s_vec, x, sp[0]->s_n); +} + +static void sigczero_rev_clear(t_sigczero_rev *x) +{ + x->x_lastre = x->x_lastim = 0; +} + +static void sigczero_rev_set(t_sigczero_rev *x, t_float re, t_float im) +{ + x->x_lastre = re; + x->x_lastim = im; +} + +void sigczero_rev_setup(void) +{ + sigczero_rev_class = class_new(gensym("czero_rev~"), + (t_newmethod)sigczero_rev_new, 0, sizeof(t_sigczero_rev), 0, + A_DEFFLOAT, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(sigczero_rev_class, t_sigczero_rev, x_f); + class_addmethod(sigczero_rev_class, (t_method)sigczero_rev_set, + gensym("set"), A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(sigczero_rev_class, (t_method)sigczero_rev_clear, + gensym("clear"), 0); + class_addmethod(sigczero_rev_class, (t_method)sigczero_rev_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ------------------------ setup routine ------------------------- */ + +void d_filter_setup(void) +{ + sighip_setup(); + siglop_setup(); + sigbp_setup(); + sigbiquad_setup(); + sigsamphold_setup(); + sigrpole_setup(); + sigrzero_setup(); + sigrzero_rev_setup(); + sigcpole_setup(); + sigczero_setup(); + sigczero_rev_setup(); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/d_global.c b/ports/camomile/source/LibPd/pure-data/src/d_global.c new file mode 100644 index 00000000..1837c295 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_global.c @@ -0,0 +1,361 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* send~, receive~, throw~, catch~ */ + +#include "m_pd.h" +#include + +#define DEFSENDVS 64 /* LATER get send to get this from canvas */ + +/* ----------------------------- send~ ----------------------------- */ +static t_class *sigsend_class; + +typedef struct _sigsend +{ + t_object x_obj; + t_symbol *x_sym; + int x_n; + t_sample *x_vec; + t_float x_f; +} t_sigsend; + +static void *sigsend_new(t_symbol *s) +{ + t_sigsend *x = (t_sigsend *)pd_new(sigsend_class); + pd_bind(&x->x_obj.ob_pd, s); + x->x_sym = s; + x->x_n = DEFSENDVS; + x->x_vec = (t_sample *)getbytes(DEFSENDVS * sizeof(t_sample)); + memset((char *)(x->x_vec), 0, DEFSENDVS * sizeof(t_sample)); + x->x_f = 0; + return (x); +} + +static t_int *sigsend_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)(w[3]); + while (n--) + { + *out = (PD_BIGORSMALL(*in) ? 0 : *in); + out++; + in++; + } + return (w+4); +} + +static void sigsend_dsp(t_sigsend *x, t_signal **sp) +{ + if (x->x_n == sp[0]->s_n) + dsp_add(sigsend_perform, 3, sp[0]->s_vec, x->x_vec, sp[0]->s_n); + else error("sigsend %s: unexpected vector size", x->x_sym->s_name); +} + +static void sigsend_free(t_sigsend *x) +{ + pd_unbind(&x->x_obj.ob_pd, x->x_sym); + freebytes(x->x_vec, x->x_n * sizeof(t_sample)); +} + +static void sigsend_setup(void) +{ + sigsend_class = class_new(gensym("send~"), (t_newmethod)sigsend_new, + (t_method)sigsend_free, sizeof(t_sigsend), 0, A_DEFSYM, 0); + class_addcreator((t_newmethod)sigsend_new, gensym("s~"), A_DEFSYM, 0); + CLASS_MAINSIGNALIN(sigsend_class, t_sigsend, x_f); + class_addmethod(sigsend_class, (t_method)sigsend_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ----------------------------- receive~ ----------------------------- */ +static t_class *sigreceive_class; + +typedef struct _sigreceive +{ + t_object x_obj; + t_symbol *x_sym; + t_sample *x_wherefrom; + int x_n; +} t_sigreceive; + +static void *sigreceive_new(t_symbol *s) +{ + t_sigreceive *x = (t_sigreceive *)pd_new(sigreceive_class); + x->x_n = DEFSENDVS; /* LATER find our vector size correctly */ + x->x_sym = s; + x->x_wherefrom = 0; + outlet_new(&x->x_obj, &s_signal); + return (x); +} + +static t_int *sigreceive_perform(t_int *w) +{ + t_sigreceive *x = (t_sigreceive *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)(w[3]); + t_sample *in = x->x_wherefrom; + if (in) + { + while (n--) + *out++ = *in++; + } + else + { + while (n--) + *out++ = 0; + } + return (w+4); +} + +/* tb: vectorized receive function */ +static t_int *sigreceive_perf8(t_int *w) +{ + t_sigreceive *x = (t_sigreceive *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)(w[3]); + t_sample *in = x->x_wherefrom; + if (in) + { + for (; n; n -= 8, in += 8, out += 8) + { + out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; out[3] = in[3]; + out[4] = in[4]; out[5] = in[5]; out[6] = in[6]; out[7] = in[7]; + } + } + else + { + for (; n; n -= 8, in += 8, out += 8) + { + out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 0; + out[4] = 0; out[5] = 0; out[6] = 0; out[7] = 0; + } + } + return (w+4); +} + +static void sigreceive_set(t_sigreceive *x, t_symbol *s) +{ + t_sigsend *sender = (t_sigsend *)pd_findbyclass((x->x_sym = s), + sigsend_class); + if (sender) + { + if (sender->x_n == x->x_n) + x->x_wherefrom = sender->x_vec; + else + { + pd_error(x, "receive~ %s: vector size mismatch", x->x_sym->s_name); + x->x_wherefrom = 0; + } + } + else + { + pd_error(x, "receive~ %s: no matching send", x->x_sym->s_name); + x->x_wherefrom = 0; + } +} + +static void sigreceive_dsp(t_sigreceive *x, t_signal **sp) +{ + if (sp[0]->s_n != x->x_n) + { + pd_error(x, "receive~ %s: vector size mismatch", x->x_sym->s_name); + } + else + { + sigreceive_set(x, x->x_sym); + if (sp[0]->s_n&7) + dsp_add(sigreceive_perform, 3, + x, sp[0]->s_vec, sp[0]->s_n); + else dsp_add(sigreceive_perf8, 3, + x, sp[0]->s_vec, sp[0]->s_n); + } +} + +static void sigreceive_setup(void) +{ + sigreceive_class = class_new(gensym("receive~"), + (t_newmethod)sigreceive_new, 0, + sizeof(t_sigreceive), 0, A_DEFSYM, 0); + class_addcreator((t_newmethod)sigreceive_new, gensym("r~"), A_DEFSYM, 0); + class_addmethod(sigreceive_class, (t_method)sigreceive_set, gensym("set"), + A_SYMBOL, 0); + class_addmethod(sigreceive_class, (t_method)sigreceive_dsp, + gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(sigreceive_class, gensym("send~")); +} + +/* ----------------------------- catch~ ----------------------------- */ +static t_class *sigcatch_class; + +typedef struct _sigcatch +{ + t_object x_obj; + t_symbol *x_sym; + int x_n; + t_sample *x_vec; +} t_sigcatch; + +static void *sigcatch_new(t_symbol *s) +{ + t_sigcatch *x = (t_sigcatch *)pd_new(sigcatch_class); + pd_bind(&x->x_obj.ob_pd, s); + x->x_sym = s; + x->x_n = DEFSENDVS; + x->x_vec = (t_sample *)getbytes(DEFSENDVS * sizeof(t_sample)); + memset((char *)(x->x_vec), 0, DEFSENDVS * sizeof(t_sample)); + outlet_new(&x->x_obj, &s_signal); + return (x); +} + +static t_int *sigcatch_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)(w[3]); + while (n--) *out++ = *in, *in++ = 0; + return (w+4); +} + +/* tb: vectorized catch function */ +static t_int *sigcatch_perf8(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)(w[3]); + for (; n; n -= 8, in += 8, out += 8) + { + out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; out[3] = in[3]; + out[4] = in[4]; out[5] = in[5]; out[6] = in[6]; out[7] = in[7]; + + in[0] = 0; in[1] = 0; in[2] = 0; in[3] = 0; + in[4] = 0; in[5] = 0; in[6] = 0; in[7] = 0; + } + return (w+4); +} + +static void sigcatch_dsp(t_sigcatch *x, t_signal **sp) +{ + if (x->x_n == sp[0]->s_n) + { + if(sp[0]->s_n&7) + dsp_add(sigcatch_perform, 3, x->x_vec, sp[0]->s_vec, sp[0]->s_n); + else + dsp_add(sigcatch_perf8, 3, x->x_vec, sp[0]->s_vec, sp[0]->s_n); + } + else error("sigcatch %s: unexpected vector size", x->x_sym->s_name); +} + +static void sigcatch_free(t_sigcatch *x) +{ + pd_unbind(&x->x_obj.ob_pd, x->x_sym); + freebytes(x->x_vec, x->x_n * sizeof(t_sample)); +} + +static void sigcatch_setup(void) +{ + sigcatch_class = class_new(gensym("catch~"), (t_newmethod)sigcatch_new, + (t_method)sigcatch_free, sizeof(t_sigcatch), CLASS_NOINLET, A_DEFSYM, 0); + class_addmethod(sigcatch_class, (t_method)sigcatch_dsp, + gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(sigcatch_class, gensym("throw~")); +} + +/* ----------------------------- throw~ ----------------------------- */ +static t_class *sigthrow_class; + +typedef struct _sigthrow +{ + t_object x_obj; + t_symbol *x_sym; + t_sample *x_whereto; + int x_n; + t_float x_f; +} t_sigthrow; + +static void *sigthrow_new(t_symbol *s) +{ + t_sigthrow *x = (t_sigthrow *)pd_new(sigthrow_class); + x->x_sym = s; + x->x_whereto = 0; + x->x_n = DEFSENDVS; + x->x_f = 0; + return (x); +} + +static t_int *sigthrow_perform(t_int *w) +{ + t_sigthrow *x = (t_sigthrow *)(w[1]); + t_sample *in = (t_sample *)(w[2]); + int n = (int)(w[3]); + t_sample *out = x->x_whereto; + if (out) + { + while (n--) + { + *out += (PD_BIGORSMALL(*in) ? 0 : *in); + out++; + in++; + } + } + return (w+4); +} + +static void sigthrow_set(t_sigthrow *x, t_symbol *s) +{ + t_sigcatch *catcher = (t_sigcatch *)pd_findbyclass((x->x_sym = s), + sigcatch_class); + if (catcher) + { + if (catcher->x_n == x->x_n) + x->x_whereto = catcher->x_vec; + else + { + pd_error(x, "throw~ %s: vector size mismatch", x->x_sym->s_name); + x->x_whereto = 0; + } + } + else + { + pd_error(x, "throw~ %s: no matching catch", x->x_sym->s_name); + x->x_whereto = 0; + } +} + +static void sigthrow_dsp(t_sigthrow *x, t_signal **sp) +{ + if (sp[0]->s_n != x->x_n) + { + pd_error(x, "throw~ %s: vector size mismatch", x->x_sym->s_name); + } + else + { + sigthrow_set(x, x->x_sym); + dsp_add(sigthrow_perform, 3, + x, sp[0]->s_vec, sp[0]->s_n); + } +} + +static void sigthrow_setup(void) +{ + sigthrow_class = class_new(gensym("throw~"), (t_newmethod)sigthrow_new, 0, + sizeof(t_sigthrow), 0, A_DEFSYM, 0); + class_addmethod(sigthrow_class, (t_method)sigthrow_set, gensym("set"), + A_SYMBOL, 0); + CLASS_MAINSIGNALIN(sigthrow_class, t_sigthrow, x_f); + class_addmethod(sigthrow_class, (t_method)sigthrow_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ----------------------- global setup routine ---------------- */ + +void d_global_setup(void) +{ + sigsend_setup(); + sigreceive_setup(); + sigcatch_setup(); + sigthrow_setup(); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/d_math.c b/ports/camomile/source/LibPd/pure-data/src/d_math.c new file mode 100644 index 00000000..d7f48711 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_math.c @@ -0,0 +1,806 @@ +/* Copyright (c) 1997-2001 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* mathematical functions and other transfer functions, including tilde + versions of stuff from x_acoustics.c. +*/ + +#include "m_pd.h" +#include +#define LOGTEN 2.302585092994 + +/* ------------------------- clip~ -------------------------- */ +static t_class *clip_class; + +typedef struct _clip +{ + t_object x_obj; + t_float x_f; + t_float x_lo; + t_float x_hi; +} t_clip; + +static void *clip_new(t_floatarg lo, t_floatarg hi) +{ + t_clip *x = (t_clip *)pd_new(clip_class); + x->x_lo = lo; + x->x_hi = hi; + outlet_new(&x->x_obj, gensym("signal")); + floatinlet_new(&x->x_obj, &x->x_lo); + floatinlet_new(&x->x_obj, &x->x_hi); + x->x_f = 0; + return (x); +} + +static t_int *clip_perform(t_int *w) +{ + t_clip *x = (t_clip *)(w[1]); + t_sample *in = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + while (n--) + { + t_sample f = *in++; + if (f < x->x_lo) f = x->x_lo; + if (f > x->x_hi) f = x->x_hi; + *out++ = f; + } + return (w+5); +} + +static void clip_dsp(t_clip *x, t_signal **sp) +{ + dsp_add(clip_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void clip_setup(void) +{ + clip_class = class_new(gensym("clip~"), (t_newmethod)clip_new, 0, + sizeof(t_clip), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(clip_class, t_clip, x_f); + class_addmethod(clip_class, (t_method)clip_dsp, gensym("dsp"), A_CANT, 0); +} + +/* sigrsqrt - reciprocal square root good to 8 mantissa bits */ + +#define DUMTAB1SIZE 256 +#define DUMTAB2SIZE 1024 + +/* These are only written at setup time when there's a global lock in place. */ +static float rsqrt_exptab[DUMTAB1SIZE], rsqrt_mantissatab[DUMTAB2SIZE]; + +static void init_rsqrt(void) +{ + int i; + for (i = 0; i < DUMTAB1SIZE; i++) + { + union { + float f; + long l; + } u; + int32_t l = (i ? (i == DUMTAB1SIZE-1 ? DUMTAB1SIZE-2 : i) : 1)<< 23; + u.l = l; + rsqrt_exptab[i] = 1./sqrt(u.f); + } + for (i = 0; i < DUMTAB2SIZE; i++) + { + float f = 1 + (1./DUMTAB2SIZE) * i; + rsqrt_mantissatab[i] = 1./sqrt(f); + } +} + + /* these are used in externs like "bonk" */ + +t_float q8_rsqrt(t_float f0) +{ + union { + float f; + long l; + } u; + u.f=f0; + if (u.f < 0) return (0); + else return (rsqrt_exptab[(u.l >> 23) & 0xff] * + rsqrt_mantissatab[(u.l >> 13) & 0x3ff]); +} + +t_float q8_sqrt(t_float f0) +{ + union { + float f; + long l; + } u; + u.f=f0; + if (u.f < 0) return (0); + else return (u.f * rsqrt_exptab[(u.l >> 23) & 0xff] * + rsqrt_mantissatab[(u.l >> 13) & 0x3ff]); +} + +t_float qsqrt(t_float f) {return (q8_sqrt(f)); } +t_float qrsqrt(t_float f) {return (q8_rsqrt(f)); } + +typedef struct sigrsqrt +{ + t_object x_obj; + t_float x_f; +} t_sigrsqrt; + +static t_class *sigrsqrt_class; + +static void *sigrsqrt_new(void) +{ + t_sigrsqrt *x = (t_sigrsqrt *)pd_new(sigrsqrt_class); + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *sigrsqrt_perform(t_int *w) +{ + t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2]; + t_int n = *(t_int *)(w+3); + while (n--) + { + t_sample f = *in++; + union { + float f; + long l; + } u; + u.f = f; + if (f < 0) *out++ = 0; + else + { + t_sample g = rsqrt_exptab[(u.l >> 23) & 0xff] * + rsqrt_mantissatab[(u.l >> 13) & 0x3ff]; + *out++ = 1.5 * g - 0.5 * g * g * g * f; + } + } + return (w + 4); +} + +static void sigrsqrt_dsp(t_sigrsqrt *x, t_signal **sp) +{ + dsp_add(sigrsqrt_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +void sigrsqrt_setup(void) +{ + init_rsqrt(); + sigrsqrt_class = class_new(gensym("rsqrt~"), (t_newmethod)sigrsqrt_new, 0, + sizeof(t_sigrsqrt), 0, 0); + /* an old name for it: */ + class_addcreator(sigrsqrt_new, gensym("q8_rsqrt~"), 0); + CLASS_MAINSIGNALIN(sigrsqrt_class, t_sigrsqrt, x_f); + class_addmethod(sigrsqrt_class, (t_method)sigrsqrt_dsp, + gensym("dsp"), A_CANT, 0); +} + + +/* sigsqrt - square root good to 8 mantissa bits */ + +typedef struct sigsqrt +{ + t_object x_obj; + t_float x_f; +} t_sigsqrt; + +static t_class *sigsqrt_class; + +static void *sigsqrt_new(void) +{ + t_sigsqrt *x = (t_sigsqrt *)pd_new(sigsqrt_class); + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +t_int *sigsqrt_perform(t_int *w) /* not static; also used in d_fft.c */ +{ + t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2]; + t_int n = *(t_int *)(w+3); + while (n--) + { + t_sample f = *in++; + union { + float f; + long l; + } u; + u.f = f; + if (f < 0) *out++ = 0; + else + { + t_sample g = rsqrt_exptab[(u.l >> 23) & 0xff] * + rsqrt_mantissatab[(u.l >> 13) & 0x3ff]; + *out++ = f * (1.5 * g - 0.5 * g * g * g * f); + } + } + return (w + 4); +} + +static void sigsqrt_dsp(t_sigsqrt *x, t_signal **sp) +{ + dsp_add(sigsqrt_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +void sigsqrt_setup(void) +{ + sigsqrt_class = class_new(gensym("sqrt~"), (t_newmethod)sigsqrt_new, 0, + sizeof(t_sigsqrt), 0, 0); + class_addcreator(sigsqrt_new, gensym("q8_sqrt~"), 0); /* old name */ + CLASS_MAINSIGNALIN(sigsqrt_class, t_sigsqrt, x_f); + class_addmethod(sigsqrt_class, (t_method)sigsqrt_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ------------------------------ wrap~ -------------------------- */ + +typedef struct wrap +{ + t_object x_obj; + t_float x_f; +} t_sigwrap; + +t_class *sigwrap_class; + +static void *sigwrap_new(void) +{ + t_sigwrap *x = (t_sigwrap *)pd_new(sigwrap_class); + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *sigwrap_perform(t_int *w) +{ + t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2]; + t_int n = (t_int)w[3]; + while (n--) + { + t_sample f = *in++; + int k = f; + if (k <= f) *out++ = f-k; + else *out++ = f - (k-1); + } + return (w + 4); +} + + /* old buggy version that sometimes output 1 instead of 0 */ +static t_int *sigwrap_old_perform(t_int *w) +{ + t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2]; + t_int n = (t_int)w[3]; + while (n--) + { + t_sample f = *in++; + int k = f; + if (f > 0) *out++ = f-k; + else *out++ = f - (k-1); + } + return (w + 4); +} + +static void sigwrap_dsp(t_sigwrap *x, t_signal **sp) +{ + dsp_add((pd_compatibilitylevel < 48 ? + sigwrap_old_perform : sigwrap_perform), + 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +void sigwrap_setup(void) +{ + sigwrap_class = class_new(gensym("wrap~"), (t_newmethod)sigwrap_new, 0, + sizeof(t_sigwrap), 0, 0); + CLASS_MAINSIGNALIN(sigwrap_class, t_sigwrap, x_f); + class_addmethod(sigwrap_class, (t_method)sigwrap_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ------------------------------ mtof_tilde~ -------------------------- */ + +typedef struct mtof_tilde +{ + t_object x_obj; + t_float x_f; +} t_mtof_tilde; + +t_class *mtof_tilde_class; + +static void *mtof_tilde_new(void) +{ + t_mtof_tilde *x = (t_mtof_tilde *)pd_new(mtof_tilde_class); + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *mtof_tilde_perform(t_int *w) +{ + t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2]; + t_int n = (t_int)w[3]; + for (; n--; in++, out++) + { + t_sample f = *in; + if (f <= -1500) *out = 0; + else + { + if (f > 1499) f = 1499; + *out = 8.17579891564 * exp(.0577622650 * f); + } + } + return (w + 4); +} + +static void mtof_tilde_dsp(t_mtof_tilde *x, t_signal **sp) +{ + dsp_add(mtof_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +void mtof_tilde_setup(void) +{ + mtof_tilde_class = class_new(gensym("mtof~"), (t_newmethod)mtof_tilde_new, 0, + sizeof(t_mtof_tilde), 0, 0); + CLASS_MAINSIGNALIN(mtof_tilde_class, t_mtof_tilde, x_f); + class_addmethod(mtof_tilde_class, (t_method)mtof_tilde_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ------------------------------ ftom_tilde~ -------------------------- */ + +typedef struct ftom_tilde +{ + t_object x_obj; + t_float x_f; +} t_ftom_tilde; + +t_class *ftom_tilde_class; + +static void *ftom_tilde_new(void) +{ + t_ftom_tilde *x = (t_ftom_tilde *)pd_new(ftom_tilde_class); + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *ftom_tilde_perform(t_int *w) +{ + t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2]; + t_int n = (t_int)w[3]; + for (; n--; in++, out++) + { + t_sample f = *in; + *out = (f > 0 ? 17.3123405046 * log(.12231220585 * f) : -1500); + } + return (w + 4); +} + +static void ftom_tilde_dsp(t_ftom_tilde *x, t_signal **sp) +{ + dsp_add(ftom_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +void ftom_tilde_setup(void) +{ + ftom_tilde_class = class_new(gensym("ftom~"), (t_newmethod)ftom_tilde_new, 0, + sizeof(t_ftom_tilde), 0, 0); + CLASS_MAINSIGNALIN(ftom_tilde_class, t_ftom_tilde, x_f); + class_addmethod(ftom_tilde_class, (t_method)ftom_tilde_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ------------------------------ dbtorms~ -------------------------- */ + +typedef struct dbtorms_tilde +{ + t_object x_obj; + t_float x_f; +} t_dbtorms_tilde; + +t_class *dbtorms_tilde_class; + +static void *dbtorms_tilde_new(void) +{ + t_dbtorms_tilde *x = (t_dbtorms_tilde *)pd_new(dbtorms_tilde_class); + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *dbtorms_tilde_perform(t_int *w) +{ + t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2]; + t_int n = (t_int)w[3]; + for (; n--; in++, out++) + { + t_sample f = *in; + if (f <= 0) *out = 0; + else + { + if (f > 485) + f = 485; + *out = exp((LOGTEN * 0.05) * (f-100.)); + } + } + return (w + 4); +} + +static void dbtorms_tilde_dsp(t_dbtorms_tilde *x, t_signal **sp) +{ + dsp_add(dbtorms_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +void dbtorms_tilde_setup(void) +{ + dbtorms_tilde_class = class_new(gensym("dbtorms~"), (t_newmethod)dbtorms_tilde_new, 0, + sizeof(t_dbtorms_tilde), 0, 0); + CLASS_MAINSIGNALIN(dbtorms_tilde_class, t_dbtorms_tilde, x_f); + class_addmethod(dbtorms_tilde_class, (t_method)dbtorms_tilde_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ------------------------------ rmstodb~ -------------------------- */ + +typedef struct rmstodb_tilde +{ + t_object x_obj; + t_float x_f; +} t_rmstodb_tilde; + +t_class *rmstodb_tilde_class; + +static void *rmstodb_tilde_new(void) +{ + t_rmstodb_tilde *x = (t_rmstodb_tilde *)pd_new(rmstodb_tilde_class); + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *rmstodb_tilde_perform(t_int *w) +{ + t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2]; + t_int n = (t_int)w[3]; + for (; n--; in++, out++) + { + t_sample f = *in; + if (f <= 0) *out = 0; + else + { + t_sample g = 100 + 20./LOGTEN * log(f); + *out = (g < 0 ? 0 : g); + } + } + return (w + 4); +} + +static void rmstodb_tilde_dsp(t_rmstodb_tilde *x, t_signal **sp) +{ + dsp_add(rmstodb_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +void rmstodb_tilde_setup(void) +{ + rmstodb_tilde_class = class_new(gensym("rmstodb~"), + (t_newmethod)rmstodb_tilde_new, 0, sizeof(t_rmstodb_tilde), 0, 0); + CLASS_MAINSIGNALIN(rmstodb_tilde_class, t_rmstodb_tilde, x_f); + class_addmethod(rmstodb_tilde_class, (t_method)rmstodb_tilde_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ------------------------------ dbtopow~ -------------------------- */ + +typedef struct dbtopow_tilde +{ + t_object x_obj; + t_float x_f; +} t_dbtopow_tilde; + +t_class *dbtopow_tilde_class; + +static void *dbtopow_tilde_new(void) +{ + t_dbtopow_tilde *x = (t_dbtopow_tilde *)pd_new(dbtopow_tilde_class); + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *dbtopow_tilde_perform(t_int *w) +{ + t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2]; + t_int n = (t_int)w[3]; + for (; n--; in++, out++) + { + t_sample f = *in; + if (f <= 0) *out = 0; + else + { + if (f > 870) + f = 870; + *out = exp((LOGTEN * 0.1) * (f-100.)); + } + } + return (w + 4); +} + +static void dbtopow_tilde_dsp(t_dbtopow_tilde *x, t_signal **sp) +{ + dsp_add(dbtopow_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +void dbtopow_tilde_setup(void) +{ + dbtopow_tilde_class = class_new(gensym("dbtopow~"), (t_newmethod)dbtopow_tilde_new, 0, + sizeof(t_dbtopow_tilde), 0, 0); + CLASS_MAINSIGNALIN(dbtopow_tilde_class, t_dbtopow_tilde, x_f); + class_addmethod(dbtopow_tilde_class, (t_method)dbtopow_tilde_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ------------------------------ powtodb~ -------------------------- */ + +typedef struct powtodb_tilde +{ + t_object x_obj; + t_float x_f; +} t_powtodb_tilde; + +t_class *powtodb_tilde_class; + +static void *powtodb_tilde_new(void) +{ + t_powtodb_tilde *x = (t_powtodb_tilde *)pd_new(powtodb_tilde_class); + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *powtodb_tilde_perform(t_int *w) +{ + t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2]; + t_int n = (t_int)w[3]; + for (; n--; in++, out++) + { + t_sample f = *in; + if (f <= 0) *out = 0; + else + { + t_sample g = 100 + 10./LOGTEN * log(f); + *out = (g < 0 ? 0 : g); + } + } + return (w + 4); +} + +static void powtodb_tilde_dsp(t_powtodb_tilde *x, t_signal **sp) +{ + dsp_add(powtodb_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +void powtodb_tilde_setup(void) +{ + powtodb_tilde_class = class_new(gensym("powtodb~"), (t_newmethod)powtodb_tilde_new, 0, + sizeof(t_powtodb_tilde), 0, 0); + CLASS_MAINSIGNALIN(powtodb_tilde_class, t_powtodb_tilde, x_f); + class_addmethod(powtodb_tilde_class, (t_method)powtodb_tilde_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ----------------------------- pow ----------------------------- */ +static t_class *pow_tilde_class; + +typedef struct _pow_tilde +{ + t_object x_obj; + t_float x_f; +} t_pow_tilde; + +static void *pow_tilde_new(t_floatarg f) +{ + t_pow_tilde *x = (t_pow_tilde *)pd_new(pow_tilde_class); + signalinlet_new(&x->x_obj, f); + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + + return (x); +} + +t_int *pow_tilde_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + while (n--) + { + float f = *in1++; + if (f > 0) + *out = pow(f, *in2); + else *out = 0; + out++; + in2++; + } + return (w+5); +} + +static void pow_tilde_dsp(t_pow_tilde *x, t_signal **sp) +{ + dsp_add(pow_tilde_perform, 4, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); +} + +static void pow_tilde_setup(void) +{ + pow_tilde_class = class_new(gensym("pow~"), (t_newmethod)pow_tilde_new, 0, + sizeof(t_pow_tilde), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(pow_tilde_class, t_pow_tilde, x_f); + class_addmethod(pow_tilde_class, (t_method)pow_tilde_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ----------------------------- exp ----------------------------- */ +static t_class *exp_tilde_class; + +typedef struct _exp_tilde +{ + t_object x_obj; + t_float x_f; +} t_exp_tilde; + +static void *exp_tilde_new( void) +{ + t_exp_tilde *x = (t_exp_tilde *)pd_new(exp_tilde_class); + outlet_new(&x->x_obj, &s_signal); + return (x); +} + +t_int *exp_tilde_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)(w[3]); + while (n--) + *out++ = exp(*in1++); + return (w+4); +} + +static void exp_tilde_dsp(t_exp_tilde *x, t_signal **sp) +{ + dsp_add(exp_tilde_perform, 3, + sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void exp_tilde_setup(void) +{ + exp_tilde_class = class_new(gensym("exp~"), (t_newmethod)exp_tilde_new, 0, + sizeof(t_exp_tilde), 0, 0); + CLASS_MAINSIGNALIN(exp_tilde_class, t_exp_tilde, x_f); + class_addmethod(exp_tilde_class, (t_method)exp_tilde_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ----------------------------- log ----------------------------- */ +static t_class *log_tilde_class; + +typedef struct _log_tilde +{ + t_object x_obj; + t_float x_f; +} t_log_tilde; + +static void *log_tilde_new(t_floatarg f) +{ + t_log_tilde *x = (t_log_tilde *)pd_new(log_tilde_class); + pd_float( + (t_pd *)inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal), f); + outlet_new(&x->x_obj, &s_signal); + x->x_f = 0; + return (x); +} + +t_int *log_tilde_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + int n = (int)(w[4]); + while (n--) + { + float f = *in1++, g = *in2++; + if (f <= 0) + *out = -1000; /* rather than blow up, output a number << 0 */ + else if (g <= 0) + *out = log(f); + else *out = log(f)/log(g); + out++; + } + return (w+5); +} + +static void log_tilde_dsp(t_log_tilde *x, t_signal **sp) +{ + dsp_add(log_tilde_perform, 4, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); +} + +static void log_tilde_setup(void) +{ + log_tilde_class = class_new(gensym("log~"), (t_newmethod)log_tilde_new, 0, + sizeof(t_log_tilde), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(log_tilde_class, t_log_tilde, x_f); + class_addmethod(log_tilde_class, (t_method)log_tilde_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ----------------------------- abs ----------------------------- */ +static t_class *abs_tilde_class; + +typedef struct _abs_tilde +{ + t_object x_obj; + t_float x_f; +} t_abs_tilde; + +static void *abs_tilde_new( void) +{ + t_abs_tilde *x = (t_abs_tilde *)pd_new(abs_tilde_class); + outlet_new(&x->x_obj, &s_signal); + return (x); +} + +t_int *abs_tilde_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)(w[3]); + while (n--) + { + float f = *in1++; + *out++ = (f >= 0 ? f : -f); + } + return (w+4); +} + +static void abs_tilde_dsp(t_abs_tilde *x, t_signal **sp) +{ + dsp_add(abs_tilde_perform, 3, + sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void abs_tilde_setup(void) +{ + abs_tilde_class = class_new(gensym("abs~"), (t_newmethod)abs_tilde_new, 0, + sizeof(t_abs_tilde), 0, 0); + CLASS_MAINSIGNALIN(abs_tilde_class, t_abs_tilde, x_f); + class_addmethod(abs_tilde_class, (t_method)abs_tilde_dsp, + gensym("dsp"), A_CANT, 0); +} + +/* ------------------------ global setup routine ------------------------- */ + +void d_math_setup(void) +{ + t_symbol *s = gensym("acoustics~.pd"); + clip_setup(); + sigrsqrt_setup(); + sigsqrt_setup(); + sigwrap_setup(); + mtof_tilde_setup(); + ftom_tilde_setup(); + dbtorms_tilde_setup(); + rmstodb_tilde_setup(); + dbtopow_tilde_setup(); + powtodb_tilde_setup(); + pow_tilde_setup(); + exp_tilde_setup(); + log_tilde_setup(); + abs_tilde_setup(); + + class_sethelpsymbol(mtof_tilde_class, s); + class_sethelpsymbol(ftom_tilde_class, s); + class_sethelpsymbol(dbtorms_tilde_class, s); + class_sethelpsymbol(rmstodb_tilde_class, s); + class_sethelpsymbol(dbtopow_tilde_class, s); + class_sethelpsymbol(powtodb_tilde_class, s); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/d_misc.c b/ports/camomile/source/LibPd/pure-data/src/d_misc.c new file mode 100644 index 00000000..b532a111 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_misc.c @@ -0,0 +1,136 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* miscellaneous: print~; more to come. +*/ + +#include "m_pd.h" +#include +#include + +/* ------------------------- print~ -------------------------- */ +static t_class *print_class; + +typedef struct _print +{ + t_object x_obj; + t_float x_f; + t_symbol *x_sym; + int x_count; +} t_print; + +static t_int *print_perform(t_int *w) +{ + t_print *x = (t_print *)(w[1]); + t_sample *in = (t_sample *)(w[2]); + int n = (int)(w[3]); + if (x->x_count) + { + int i=0; + startpost("%s:", x->x_sym->s_name); + for(i=0; ix_count--; + } + return (w+4); +} + +static void print_dsp(t_print *x, t_signal **sp) +{ + dsp_add(print_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); +} + +static void print_float(t_print *x, t_float f) +{ + if (f < 0) f = 0; + x->x_count = f; +} + +static void print_bang(t_print *x) +{ + x->x_count = 1; +} + +static void *print_new(t_symbol *s) +{ + t_print *x = (t_print *)pd_new(print_class); + x->x_sym = (s->s_name[0]? s : gensym("print~")); + x->x_count = 0; + x->x_f = 0; + return (x); +} + +static void print_setup(void) +{ + print_class = class_new(gensym("print~"), (t_newmethod)print_new, 0, + sizeof(t_print), 0, A_DEFSYM, 0); + CLASS_MAINSIGNALIN(print_class, t_print, x_f); + class_addmethod(print_class, (t_method)print_dsp, gensym("dsp"), A_CANT, 0); + class_addbang(print_class, print_bang); + class_addfloat(print_class, print_float); +} + +/* ------------------------ bang~ -------------------------- */ + +static t_class *bang_tilde_class; + +typedef struct _bang +{ + t_object x_obj; + t_clock *x_clock; +} t_bang; + +static t_int *bang_tilde_perform(t_int *w) +{ + t_bang *x = (t_bang *)(w[1]); + clock_delay(x->x_clock, 0); + return (w+2); +} + +static void bang_tilde_dsp(t_bang *x, t_signal **sp) +{ + dsp_add(bang_tilde_perform, 1, x); +} + +static void bang_tilde_tick(t_bang *x) +{ + outlet_bang(x->x_obj.ob_outlet); +} + +static void bang_tilde_free(t_bang *x) +{ + clock_free(x->x_clock); +} + +static void *bang_tilde_new(t_symbol *s) +{ + t_bang *x = (t_bang *)pd_new(bang_tilde_class); + x->x_clock = clock_new(x, (t_method)bang_tilde_tick); + outlet_new(&x->x_obj, &s_bang); + return (x); +} + +static void bang_tilde_setup(void) +{ + bang_tilde_class = class_new(gensym("bang~"), (t_newmethod)bang_tilde_new, + (t_method)bang_tilde_free, sizeof(t_bang), 0, 0); + class_addmethod(bang_tilde_class, (t_method)bang_tilde_dsp, + gensym("dsp"), 0); +} + + +/* ------------------------ global setup routine ------------------------- */ + +void d_misc_setup(void) +{ + print_setup(); + bang_tilde_setup(); +} + + + + diff --git a/ports/camomile/source/LibPd/pure-data/src/d_osc.c b/ports/camomile/source/LibPd/pure-data/src/d_osc.c new file mode 100644 index 00000000..e32b89f3 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_osc.c @@ -0,0 +1,521 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* sinusoidal oscillator and table lookup; see also tabosc4~ in d_array.c. +*/ + +#include "m_pd.h" +#include "math.h" + +#define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */ + + +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) \ + || defined(__OpenBSD__) +#include +#endif + +#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || \ + defined(ANDROID) +#include +#endif + +#ifdef __MINGW32__ +#include +#endif + +#ifdef _MSC_VER +/* _MSVC lacks BYTE_ORDER and LITTLE_ENDIAN */ +#define LITTLE_ENDIAN 0x0001 +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) +#error No byte order defined +#endif + +#if BYTE_ORDER == LITTLE_ENDIAN +# define HIOFFSET 1 +# define LOWOFFSET 0 +#else +# define HIOFFSET 0 /* word offset to find MSB */ +# define LOWOFFSET 1 /* word offset to find LSB */ +#endif + +union tabfudge +{ + double tf_d; + int32_t tf_i[2]; +}; + +/* -------------------------- phasor~ ------------------------------ */ +static t_class *phasor_class; + +#if 1 /* in the style of R. Hoeldrich (ICMC 1995 Banff) */ + +typedef struct _phasor +{ + t_object x_obj; + double x_phase; + float x_conv; + float x_f; /* scalar frequency */ +} t_phasor; + +static void *phasor_new(t_floatarg f) +{ + t_phasor *x = (t_phasor *)pd_new(phasor_class); + x->x_f = f; + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1")); + x->x_phase = 0; + x->x_conv = 0; + outlet_new(&x->x_obj, gensym("signal")); + return (x); +} + +static t_int *phasor_perform(t_int *w) +{ + t_phasor *x = (t_phasor *)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + int n = (int)(w[4]); + double dphase = x->x_phase + (double)UNITBIT32; + union tabfudge tf; + int normhipart; + float conv = x->x_conv; + + tf.tf_d = UNITBIT32; + normhipart = tf.tf_i[HIOFFSET]; + tf.tf_d = dphase; + + while (n--) + { + tf.tf_i[HIOFFSET] = normhipart; + dphase += *in++ * conv; + *out++ = tf.tf_d - UNITBIT32; + tf.tf_d = dphase; + } + tf.tf_i[HIOFFSET] = normhipart; + x->x_phase = tf.tf_d - UNITBIT32; + return (w+5); +} + +static void phasor_dsp(t_phasor *x, t_signal **sp) +{ + x->x_conv = 1./sp[0]->s_sr; + dsp_add(phasor_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void phasor_ft1(t_phasor *x, t_float f) +{ + x->x_phase = f; +} + +static void phasor_setup(void) +{ + phasor_class = class_new(gensym("phasor~"), (t_newmethod)phasor_new, 0, + sizeof(t_phasor), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(phasor_class, t_phasor, x_f); + class_addmethod(phasor_class, (t_method)phasor_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(phasor_class, (t_method)phasor_ft1, + gensym("ft1"), A_FLOAT, 0); +} + +#endif /* Hoeldrich version */ + +/* ------------------------ cos~ ----------------------------- */ + +float *cos_table; + +static t_class *cos_class; + +typedef struct _cos +{ + t_object x_obj; + float x_f; +} t_cos; + +static void *cos_new(void) +{ + t_cos *x = (t_cos *)pd_new(cos_class); + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *cos_perform(t_int *w) +{ + t_float *in = (t_float *)(w[1]); + t_float *out = (t_float *)(w[2]); + int n = (int)(w[3]); + float *tab = cos_table, *addr, f1, f2, frac; + double dphase; + int normhipart; + union tabfudge tf; + + tf.tf_d = UNITBIT32; + normhipart = tf.tf_i[HIOFFSET]; + +#if 0 /* this is the readable version of the code. */ + while (n--) + { + dphase = (double)(*in++ * (float)(COSTABSIZE)) + UNITBIT32; + tf.tf_d = dphase; + addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1)); + tf.tf_i[HIOFFSET] = normhipart; + frac = tf.tf_d - UNITBIT32; + f1 = addr[0]; + f2 = addr[1]; + *out++ = f1 + frac * (f2 - f1); + } +#endif +#if 1 /* this is the same, unwrapped by hand. */ + dphase = (double)(*in++ * (float)(COSTABSIZE)) + UNITBIT32; + tf.tf_d = dphase; + addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1)); + tf.tf_i[HIOFFSET] = normhipart; + while (--n) + { + dphase = (double)(*in++ * (float)(COSTABSIZE)) + UNITBIT32; + frac = tf.tf_d - UNITBIT32; + tf.tf_d = dphase; + f1 = addr[0]; + f2 = addr[1]; + addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1)); + *out++ = f1 + frac * (f2 - f1); + tf.tf_i[HIOFFSET] = normhipart; + } + frac = tf.tf_d - UNITBIT32; + f1 = addr[0]; + f2 = addr[1]; + *out++ = f1 + frac * (f2 - f1); +#endif + return (w+4); +} + +static void cos_dsp(t_cos *x, t_signal **sp) +{ + dsp_add(cos_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void cos_maketable(void) +{ + int i; + float *fp, phase, phsinc = (2. * 3.14159) / COSTABSIZE; + union tabfudge tf; + + if (cos_table) return; + cos_table = (float *)getbytes(sizeof(float) * (COSTABSIZE+1)); + for (i = COSTABSIZE + 1, fp = cos_table, phase = 0; i--; + fp++, phase += phsinc) + *fp = cos(phase); + + /* here we check at startup whether the byte alignment + is as we declared it. If not, the code has to be + recompiled the other way. */ + tf.tf_d = UNITBIT32 + 0.5; + if ((unsigned)tf.tf_i[LOWOFFSET] != 0x80000000) + bug("cos~: unexpected machine alignment"); +} + +static void cos_setup(void) +{ + cos_class = class_new(gensym("cos~"), (t_newmethod)cos_new, 0, + sizeof(t_cos), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(cos_class, t_cos, x_f); + class_addmethod(cos_class, (t_method)cos_dsp, gensym("dsp"), A_CANT, 0); + cos_maketable(); +} + +/* ------------------------ osc~ ----------------------------- */ + +static t_class *osc_class, *scalarosc_class; + +typedef struct _osc +{ + t_object x_obj; + double x_phase; + float x_conv; + float x_f; /* frequency if scalar */ +} t_osc; + +static void *osc_new(t_floatarg f) +{ + t_osc *x = (t_osc *)pd_new(osc_class); + x->x_f = f; + outlet_new(&x->x_obj, gensym("signal")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1")); + x->x_phase = 0; + x->x_conv = 0; + return (x); +} + +static t_int *osc_perform(t_int *w) +{ + t_osc *x = (t_osc *)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + int n = (int)(w[4]); + float *tab = cos_table, *addr, f1, f2, frac; + double dphase = x->x_phase + UNITBIT32; + int normhipart; + union tabfudge tf; + float conv = x->x_conv; + + tf.tf_d = UNITBIT32; + normhipart = tf.tf_i[HIOFFSET]; +#if 0 + while (n--) + { + tf.tf_d = dphase; + dphase += *in++ * conv; + addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1)); + tf.tf_i[HIOFFSET] = normhipart; + frac = tf.tf_d - UNITBIT32; + f1 = addr[0]; + f2 = addr[1]; + *out++ = f1 + frac * (f2 - f1); + } +#endif +#if 1 + tf.tf_d = dphase; + dphase += *in++ * conv; + addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1)); + tf.tf_i[HIOFFSET] = normhipart; + frac = tf.tf_d - UNITBIT32; + while (--n) + { + tf.tf_d = dphase; + f1 = addr[0]; + dphase += *in++ * conv; + f2 = addr[1]; + addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1)); + tf.tf_i[HIOFFSET] = normhipart; + *out++ = f1 + frac * (f2 - f1); + frac = tf.tf_d - UNITBIT32; + } + f1 = addr[0]; + f2 = addr[1]; + *out++ = f1 + frac * (f2 - f1); +#endif + + tf.tf_d = UNITBIT32 * COSTABSIZE; + normhipart = tf.tf_i[HIOFFSET]; + tf.tf_d = dphase + (UNITBIT32 * COSTABSIZE - UNITBIT32); + tf.tf_i[HIOFFSET] = normhipart; + x->x_phase = tf.tf_d - UNITBIT32 * COSTABSIZE; + return (w+5); +} + +static void osc_dsp(t_osc *x, t_signal **sp) +{ + x->x_conv = COSTABSIZE/sp[0]->s_sr; + dsp_add(osc_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void osc_ft1(t_osc *x, t_float f) +{ + x->x_phase = COSTABSIZE * f; +} + +static void osc_setup(void) +{ + osc_class = class_new(gensym("osc~"), (t_newmethod)osc_new, 0, + sizeof(t_osc), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(osc_class, t_osc, x_f); + class_addmethod(osc_class, (t_method)osc_dsp, gensym("dsp"), A_CANT, 0); + class_addmethod(osc_class, (t_method)osc_ft1, gensym("ft1"), A_FLOAT, 0); + + cos_maketable(); +} + +/* ---- vcf~ - resonant filter with audio-rate center frequency input ----- */ + +typedef struct vcfctl +{ + float c_re; + float c_im; + float c_q; + float c_isr; +} t_vcfctl; + +typedef struct sigvcf +{ + t_object x_obj; + t_vcfctl x_cspace; + t_vcfctl *x_ctl; + float x_f; +} t_sigvcf; + +t_class *sigvcf_class; + +static void *sigvcf_new(t_floatarg q) +{ + t_sigvcf *x = (t_sigvcf *)pd_new(sigvcf_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1")); + outlet_new(&x->x_obj, gensym("signal")); + outlet_new(&x->x_obj, gensym("signal")); + x->x_ctl = &x->x_cspace; + x->x_cspace.c_re = 0; + x->x_cspace.c_im = 0; + x->x_cspace.c_q = q; + x->x_cspace.c_isr = 0; + x->x_f = 0; + return (x); +} + +static void sigvcf_ft1(t_sigvcf *x, t_floatarg f) +{ + x->x_ctl->c_q = (f > 0 ? f : 0.f); +} + +static t_int *sigvcf_perform(t_int *w) +{ + float *in1 = (float *)(w[1]); + float *in2 = (float *)(w[2]); + float *out1 = (float *)(w[3]); + float *out2 = (float *)(w[4]); + t_vcfctl *c = (t_vcfctl *)(w[5]); + int n = (int)w[6]; + int i; + float re = c->c_re, re2; + float im = c->c_im; + float q = c->c_q; + float qinv = (q > 0? 1.0f/q : 0); + float ampcorrect = 2.0f - 2.0f / (q + 2.0f); + float isr = c->c_isr; + float coefr, coefi; + float *tab = cos_table, *addr, f1, f2, frac; + double dphase; + int normhipart, tabindex; + union tabfudge tf; + + tf.tf_d = UNITBIT32; + normhipart = tf.tf_i[HIOFFSET]; + + for (i = 0; i < n; i++) + { + float cf, cfindx, r, oneminusr; + cf = *in2++ * isr; + if (cf < 0) cf = 0; + cfindx = cf * (float)(COSTABSIZE/6.28318f); + r = (qinv > 0 ? 1 - cf * qinv : 0); + if (r < 0) r = 0; + oneminusr = 1.0f - r; + dphase = ((double)(cfindx)) + UNITBIT32; + tf.tf_d = dphase; + tabindex = tf.tf_i[HIOFFSET] & (COSTABSIZE-1); + addr = tab + tabindex; + tf.tf_i[HIOFFSET] = normhipart; + frac = tf.tf_d - UNITBIT32; + f1 = addr[0]; + f2 = addr[1]; + coefr = r * (f1 + frac * (f2 - f1)); + + addr = tab + ((tabindex - (COSTABSIZE/4)) & (COSTABSIZE-1)); + f1 = addr[0]; + f2 = addr[1]; + coefi = r * (f1 + frac * (f2 - f1)); + + f1 = *in1++; + re2 = re; + *out1++ = re = ampcorrect * oneminusr * f1 + + coefr * re2 - coefi * im; + *out2++ = im = coefi * re2 + coefr * im; + } + if (PD_BIGORSMALL(re)) + re = 0; + if (PD_BIGORSMALL(im)) + im = 0; + c->c_re = re; + c->c_im = im; + return (w+7); +} + +static void sigvcf_dsp(t_sigvcf *x, t_signal **sp) +{ + x->x_ctl->c_isr = 6.28318f/sp[0]->s_sr; + dsp_add(sigvcf_perform, 6, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, + x->x_ctl, sp[0]->s_n); +} + +void sigvcf_setup(void) +{ + sigvcf_class = class_new(gensym("vcf~"), (t_newmethod)sigvcf_new, 0, + sizeof(t_sigvcf), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(sigvcf_class, t_sigvcf, x_f); + class_addmethod(sigvcf_class, (t_method)sigvcf_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(sigvcf_class, (t_method)sigvcf_ft1, + gensym("ft1"), A_FLOAT, 0); +} + +/* -------------------------- noise~ ------------------------------ */ +static t_class *noise_class; + +typedef struct _noise +{ + t_object x_obj; + int x_val; +} t_noise; + +static void *noise_new(void) +{ + t_noise *x = (t_noise *)pd_new(noise_class); + /* seed each instance differently. Once in a blue moon two threads + could grab the same seed value. We can live with that. */ + static int init = 307; + x->x_val = (init *= 1319); + outlet_new(&x->x_obj, gensym("signal")); + return (x); +} + +static t_int *noise_perform(t_int *w) +{ + t_sample *out = (t_sample *)(w[1]); + int *vp = (int *)(w[2]); + int n = (int)(w[3]); + int val = *vp; + while (n--) + { + *out++ = ((float)((val & 0x7fffffff) - 0x40000000)) * + (float)(1.0 / 0x40000000); + val = val * 435898247 + 382842987; + } + *vp = val; + return (w+4); +} + +static void noise_dsp(t_noise *x, t_signal **sp) +{ + dsp_add(noise_perform, 3, sp[0]->s_vec, &x->x_val, sp[0]->s_n); +} + +static void noise_float(t_noise *x, t_float f) +{ + /* set the seed */ + x->x_val = (int)f; +} + +static void noise_setup(void) +{ + noise_class = class_new(gensym("noise~"), (t_newmethod)noise_new, 0, + sizeof(t_noise), 0, A_DEFFLOAT, 0); + class_addmethod(noise_class, (t_method)noise_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(noise_class, (t_method)noise_float, + gensym("seed"), A_FLOAT, 0); +} + +/* ----------------------- global setup routine ---------------- */ +void d_osc_setup(void) +{ + phasor_setup(); + cos_setup(); + osc_setup(); + sigvcf_setup(); + noise_setup(); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/d_resample.c b/ports/camomile/source/LibPd/pure-data/src/d_resample.c new file mode 100644 index 00000000..08979097 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_resample.c @@ -0,0 +1,216 @@ +/* Copyright (c) 1997-1999 Miller Puckette. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + + +#include "m_pd.h" + +/* --------------------- up/down-sampling --------------------- */ +t_int *downsampling_perform_0(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); /* original signal */ + t_sample *out = (t_sample *)(w[2]); /* downsampled signal */ + int down = (int)(w[3]); /* downsampling factor */ + int parent = (int)(w[4]); /* original vectorsize */ + + int n=parent/down; + + while(n--){ + *out++=*in; + in+=down; + } + + return (w+5); +} + +t_int *upsampling_perform_0(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); /* original signal */ + t_sample *out = (t_sample *)(w[2]); /* upsampled signal */ + int up = (int)(w[3]); /* upsampling factor */ + int parent = (int)(w[4]); /* original vectorsize */ + + int n=parent*up; + t_sample *dummy = out; + + while(n--)*out++=0; + + n = parent; + out = dummy; + while(n--){ + *out=*in++; + out+=up; + } + + return (w+5); +} + +t_int *upsampling_perform_hold(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); /* original signal */ + t_sample *out = (t_sample *)(w[2]); /* upsampled signal */ + int up = (int)(w[3]); /* upsampling factor */ + int parent = (int)(w[4]); /* original vectorsize */ + int i=up; + + int n=parent; + t_sample *dum_out = out; + t_sample *dum_in = in; + + while (i--) { + n = parent; + out = dum_out+i; + in = dum_in; + while(n--){ + *out=*in++; + out+=up; + } + } + return (w+5); +} + +t_int *upsampling_perform_linear(t_int *w) +{ + t_resample *x= (t_resample *)(w[1]); + t_sample *in = (t_sample *)(w[2]); /* original signal */ + t_sample *out = (t_sample *)(w[3]); /* upsampled signal */ + int up = (int)(w[4]); /* upsampling factor */ + int parent = (int)(w[5]); /* original vectorsize */ + int length = parent*up; + int n; + t_sample *fp; + t_sample a=*x->buffer, b=*in; + + + for (n=0; nbuffer = a; + return (w+6); +} + +/* ----------------------- public -------------------------------- */ + +/* utils */ + +void resample_init(t_resample *x) +{ + x->method=0; + + x->downsample=x->upsample=1; + + x->s_n = x->coefsize = x->bufsize = 0; + x->s_vec = x->coeffs = x->buffer = 0; +} + +void resample_free(t_resample *x) +{ + if (x->s_n) t_freebytes(x->s_vec, x->s_n*sizeof(*x->s_vec)); + if (x->coefsize) t_freebytes(x->coeffs, x->coefsize*sizeof(*x->coeffs)); + if (x->bufsize) t_freebytes(x->buffer, x->bufsize*sizeof(*x->buffer)); + + x->s_n = x->coefsize = x->bufsize = 0; + x->s_vec = x->coeffs = x->buffer = 0; +} + + +/* dsp-adding */ + +void resample_dsp(t_resample *x, + t_sample* in, int insize, + t_sample* out, int outsize, + int method) +{ + if (insize == outsize){ + bug("nothing to be done"); + return; + } + + if (insize > outsize) { /* downsampling */ + if (insize % outsize) { + error("bad downsampling factor"); + return; + } + switch (method) { + default: + dsp_add(downsampling_perform_0, 4, in, out, insize/outsize, insize); + } + + + } else { /* upsampling */ + if (outsize % insize) { + error("bad upsampling factor"); + return; + } + switch (method) { + case 1: + dsp_add(upsampling_perform_hold, 4, in, out, outsize/insize, insize); + break; + case 2: + if (x->bufsize != 1) { + t_freebytes(x->buffer, x->bufsize*sizeof(*x->buffer)); + x->bufsize = 1; + x->buffer = t_getbytes(x->bufsize*sizeof(*x->buffer)); + } + dsp_add(upsampling_perform_linear, 5, x, in, out, outsize/insize, insize); + break; + default: + dsp_add(upsampling_perform_0, 4, in, out, outsize/insize, insize); + } + } +} + +void resamplefrom_dsp(t_resample *x, + t_sample *in, + int insize, int outsize, int method) +{ + if (insize==outsize) { + t_freebytes(x->s_vec, x->s_n * sizeof(*x->s_vec)); + x->s_n = 0; + x->s_vec = in; + return; + } + + if (x->s_n != outsize) { + t_sample *buf=x->s_vec; + t_freebytes(buf, x->s_n * sizeof(*buf)); + buf = (t_sample *)t_getbytes(outsize * sizeof(*buf)); + x->s_vec = buf; + x->s_n = outsize; + } + + resample_dsp(x, in, insize, x->s_vec, x->s_n, method); + return; +} + +void resampleto_dsp(t_resample *x, + t_sample *out, + int insize, int outsize, int method) +{ + if (insize==outsize) { + if (x->s_n)t_freebytes(x->s_vec, x->s_n * sizeof(*x->s_vec)); + x->s_n = 0; + x->s_vec = out; + return; + } + + if (x->s_n != insize) { + t_sample *buf=x->s_vec; + t_freebytes(buf, x->s_n * sizeof(*buf)); + buf = (t_sample *)t_getbytes(insize * sizeof(*buf)); + x->s_vec = buf; + x->s_n = insize; + } + + resample_dsp(x, x->s_vec, x->s_n, out, outsize, method); + + return; +} diff --git a/ports/camomile/source/LibPd/pure-data/src/d_soundfile.c b/ports/camomile/source/LibPd/pure-data/src/d_soundfile.c new file mode 100644 index 00000000..3209e822 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_soundfile.c @@ -0,0 +1,2734 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* this file contains, first, a collection of soundfile access routines, a +sort of soundfile library. Second, the "soundfiler" object is defined which +uses the routines to read or write soundfiles, synchronously, from garrays. +These operations are not to be done in "real time" as they may have to wait +for disk accesses (even the write routine.) Finally, the realtime objects +readsf~ and writesf~ are defined which confine disk operations to a separate +thread so that they can be used in real time. The readsf~ and writesf~ +objects use Posix-like threads. */ + +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#ifdef _WIN32 +#include +#endif +#include +#include +#include +#include +#include + +#include "m_pd.h" + +#define MAXSFCHANS 64 + +#ifdef _LARGEFILE64_SOURCE +# define open open64 +# define lseek lseek64 +#define off_t __off64_t +#endif + +/* Microsoft Visual Studio does not define these... arg */ +#ifdef _MSC_VER +#define off_t long +#define O_CREAT _O_CREAT +#define O_TRUNC _O_TRUNC +#define O_WRONLY _O_WRONLY +#endif + +/***************** soundfile header structures ************************/ + +typedef union _samplelong { + t_sample f; + long l; +} t_sampleuint; + +#define FORMAT_WAVE 0 +#define FORMAT_AIFF 1 +#define FORMAT_NEXT 2 + +/* the NeXTStep sound header structure; can be big or little endian */ + +typedef struct _nextstep +{ + char ns_fileid[4]; /* magic number '.snd' if file is big-endian */ + uint32_t ns_onset; /* byte offset of first sample */ + uint32_t ns_length; /* length of sound in bytes */ + uint32_t ns_format; /* format; see below */ + uint32_t ns_sr; /* sample rate */ + uint32_t ns_nchans; /* number of channels */ + char ns_info[4]; /* comment */ +} t_nextstep; + +#define NS_FORMAT_LINEAR_16 3 +#define NS_FORMAT_LINEAR_24 4 +#define NS_FORMAT_FLOAT 6 +#define SCALE (1./(1024. * 1024. * 1024. * 2.)) + +/* the WAVE header. All Wave files are little endian. We assume + the "fmt" chunk comes first which is usually the case but perhaps not + always; same for AIFF and the "COMM" chunk. */ + +typedef unsigned word; +typedef unsigned long dword; + +typedef struct _wave +{ + char w_fileid[4]; /* chunk id 'RIFF' */ + uint32_t w_chunksize; /* chunk size */ + char w_waveid[4]; /* wave chunk id 'WAVE' */ + char w_fmtid[4]; /* format chunk id 'fmt ' */ + uint32_t w_fmtchunksize; /* format chunk size */ + uint16_t w_fmttag; /* format tag (WAV_INT etc) */ + uint16_t w_nchannels; /* number of channels */ + uint32_t w_samplespersec; /* sample rate in hz */ + uint32_t w_navgbytespersec; /* average bytes per second */ + uint16_t w_nblockalign; /* number of bytes per frame */ + uint16_t w_nbitspersample; /* number of bits in a sample */ + char w_datachunkid[4]; /* data chunk id 'data' */ + uint32_t w_datachunksize; /* length of data chunk */ +} t_wave; + +typedef struct _fmt /* format chunk */ +{ + uint16_t f_fmttag; /* format tag, 1 for PCM */ + uint16_t f_nchannels; /* number of channels */ + uint32_t f_samplespersec; /* sample rate in hz */ + uint32_t f_navgbytespersec; /* average bytes per second */ + uint16_t f_nblockalign; /* number of bytes per frame */ + uint16_t f_nbitspersample; /* number of bits in a sample */ +} t_fmt; + +typedef struct _wavechunk /* ... and the last two items */ +{ + char wc_id[4]; /* data chunk id, e.g., 'data' or 'fmt ' */ + uint32_t wc_size; /* length of data chunk */ +} t_wavechunk; + +#define WAV_INT 1 +#define WAV_FLOAT 3 + +/* the AIFF header. I'm assuming AIFC is compatible but don't really know + that. */ + +typedef struct _datachunk +{ + char dc_id[4]; /* data chunk id 'SSND' */ + uint32_t dc_size; /* length of data chunk */ + uint32_t dc_offset; /* additional offset in bytes */ + uint32_t dc_block; /* block size */ +} t_datachunk; + +typedef struct _comm +{ + uint16_t c_nchannels; /* number of channels */ + uint16_t c_nframeshi; /* # of sample frames (hi) */ + uint16_t c_nframeslo; /* # of sample frames (lo) */ + uint16_t c_bitspersamp; /* bits per sample */ + unsigned char c_samprate[10]; /* sample rate, 80-bit float! */ +} t_comm; + + /* this version is more convenient for writing them out: */ +typedef struct _aiff +{ + char a_fileid[4]; /* chunk id 'FORM' */ + uint32_t a_chunksize; /* chunk size */ + char a_aiffid[4]; /* aiff chunk id 'AIFF' */ + char a_fmtid[4]; /* format chunk id 'COMM' */ + uint32_t a_fmtchunksize; /* format chunk size, 18 */ + uint16_t a_nchannels; /* number of channels */ + uint16_t a_nframeshi; /* # of sample frames (hi) */ + uint16_t a_nframeslo; /* # of sample frames (lo) */ + uint16_t a_bitspersamp; /* bits per sample */ + unsigned char a_samprate[10]; /* sample rate, 80-bit float! */ +} t_aiff; + +#define AIFFHDRSIZE 38 /* probably not what sizeof() gives */ +#define AIFFPLUS (AIFFHDRSIZE + 16) /* header size including SSND chunk hdr */ + +#define WHDR1 sizeof(t_nextstep) +#define WHDR2 (sizeof(t_wave) > WHDR1 ? sizeof (t_wave) : WHDR1) +#define WRITEHDRSIZE (AIFFPLUS > WHDR2 ? AIFFPLUS : WHDR2) + +#define READHDRSIZE (16 > WHDR2 + 2 ? 16 : WHDR2 + 2) + +#define OBUFSIZE MAXPDSTRING /* assume MAXPDSTRING is bigger than headers */ + +/* this routine returns 1 if the high order byte comes at the lower +address on our architecture (big-endianness.). It's 1 for Motorola, +0 for Intel: */ + +extern int garray_ambigendian(void); + +/* byte swappers */ + +static uint32_t swap4(uint32_t n, int doit) +{ + if (doit) + return (((n & 0xff) << 24) | ((n & 0xff00) << 8) | + ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24)); + else return (n); +} + +static uint16_t swap2(uint32_t n, int doit) +{ + if (doit) + return (((n & 0xff) << 8) | ((n & 0xff00) >> 8)); + else return (n); +} + +static void swapstring(char *foo, int doit) +{ + if (doit) + { + char a = foo[0], b = foo[1], c = foo[2], d = foo[3]; + foo[0] = d; foo[1] = c; foo[2] = b; foo[3] = a; + } +} + + /* read sample rate from an 80-bit AIFF-compatible number */ +static double readaiffsamprate(char * shit, int swap) +{ + unsigned long mantissa, last = 0; + unsigned char exp; + + swapstring(shit+2, swap); + + mantissa = (unsigned long) *((unsigned long *)(shit+2)); + exp = 30 - *(shit+1); + while (exp--) + { + last = mantissa; + mantissa >>= 1; + } + if (last & 0x00000001) mantissa++; + return mantissa; +} + + /* write a sample rate as an 80-bit AIFF-compatible number */ +static void makeaiffsamprate(double sr, unsigned char *shit) +{ + int exponent; + double mantissa = frexp(sr, &exponent); + unsigned long fixmantissa = ldexp(mantissa, 32); + shit[0] = (exponent+16382)>>8; + shit[1] = exponent+16382; + shit[2] = fixmantissa >> 24; + shit[3] = fixmantissa >> 16; + shit[4] = fixmantissa >> 8; + shit[5] = fixmantissa; + shit[6] = shit[7] = shit[8] = shit[9] = 0; +} + +/******************** soundfile access routines **********************/ + +typedef struct _soundfile_info +{ + int samplerate; + int channels; + int bytespersample; + int headersize; + int bigendian; + long bytelimit; +} t_soundfile_info; + +static void outlet_soundfile_info(t_outlet *out, t_soundfile_info *info) +{ + t_atom info_list[5]; + SETFLOAT((t_atom *)info_list, (t_float)info->samplerate); + SETFLOAT((t_atom *)info_list+1, (t_float)(info->headersize < 0 ? 0 : info->headersize)); + SETFLOAT((t_atom *)info_list+2, (t_float)info->channels); + SETFLOAT((t_atom *)info_list+3, (t_float)info->bytespersample); + SETSYMBOL((t_atom *)info_list+4, gensym((info->bigendian ? "b" : "l"))); + outlet_list(out, &s_list, 5, (t_atom *)info_list); +} + +/* This routine opens a file, looks for either a nextstep or "wave" header, +* seeks to end of it, and fills in bytes per sample and number of channels. +* Only 2- and 3-byte fixed-point samples and 4-byte floating point samples +* are supported. If "headersize" is nonzero, the +* caller should supply the number of channels, endinanness, and bytes per +* sample; the header is ignored. Otherwise, the routine tries to read the +* header and fill in the properties. +*/ + +int open_soundfile_via_fd(int fd, t_soundfile_info *p_info, long skipframes) +{ + int format, nchannels, bigendian, bytespersamp, samprate, swap; + int headersize = 0; + long sysrtn, bytelimit = 0x7fffffff; + errno = 0; + if (p_info->headersize >= 0) /* header detection overridden */ + { + headersize = p_info->headersize; + bigendian = p_info->bigendian; + nchannels = p_info->channels; + bytespersamp = p_info->bytespersample; + bytelimit = p_info->bytelimit; + samprate = p_info->samplerate; + } + else + { + union + { + char b_c[OBUFSIZE]; + t_fmt b_fmt; + t_nextstep b_nextstep; + t_wavechunk b_wavechunk; + t_datachunk b_datachunk; + t_comm b_commchunk; + } buf; + long bytesread = read(fd, buf.b_c, READHDRSIZE); + int format; + if (bytesread < 4) + goto badheader; + if (!strncmp(buf.b_c, ".snd", 4)) + format = FORMAT_NEXT, bigendian = 1; + else if (!strncmp(buf.b_c, "dns.", 4)) + format = FORMAT_NEXT, bigendian = 0; + else if (!strncmp(buf.b_c, "RIFF", 4)) + { + if (bytesread < 12 || strncmp(buf.b_c + 8, "WAVE", 4)) + goto badheader; + format = FORMAT_WAVE, bigendian = 0; + } + else if (!strncmp(buf.b_c, "FORM", 4)) + { + if (bytesread < 12 || strncmp(buf.b_c + 8, "AIFF", 4)) + goto badheader; + format = FORMAT_AIFF, bigendian = 1; + } + else + goto badheader; + swap = (bigendian != garray_ambigendian()); + if (format == FORMAT_NEXT) /* nextstep header */ + { + t_nextstep *nsbuf = &buf.b_nextstep; + if (bytesread < (int)sizeof(t_nextstep)) + goto badheader; + nchannels = swap4(nsbuf->ns_nchans, swap); + format = swap4(nsbuf->ns_format, swap); + headersize = swap4(nsbuf->ns_onset, swap); + if (format == NS_FORMAT_LINEAR_16) + bytespersamp = 2; + else if (format == NS_FORMAT_LINEAR_24) + bytespersamp = 3; + else if (format == NS_FORMAT_FLOAT) + bytespersamp = 4; + else goto badheader; + bytelimit = 0x7fffffff; + samprate = swap4(nsbuf->ns_sr, swap); + } + else if (format == FORMAT_WAVE) /* wave header */ + { + t_wavechunk *wavechunk = &buf.b_wavechunk; + /* This is awful. You have to skip over chunks, + except that if one happens to be a "fmt" chunk, you want to + find out the format from that one. The case where the + "fmt" chunk comes after the audio isn't handled. */ + headersize = 12; + if (bytesread < 20) + goto badheader; + /* First we guess a number of channels, etc., in case there's + no "fmt" chunk to follow. */ + nchannels = 1; + bytespersamp = 2; + samprate = 44100; + /* copy the first chunk header to beginnning of buffer. */ + memcpy(buf.b_c, buf.b_c + headersize, sizeof(t_wavechunk)); + /* post("chunk %c %c %c %c", + ((t_wavechunk *)buf)->wc_id[0], + ((t_wavechunk *)buf)->wc_id[1], + ((t_wavechunk *)buf)->wc_id[2], + ((t_wavechunk *)buf)->wc_id[3]); */ + /* read chunks in loop until we get to the data chunk */ + while (strncmp(wavechunk->wc_id, "data", 4)) + { + long chunksize = swap4(wavechunk->wc_size, + swap), seekto = headersize + chunksize + 8, seekout; + if (seekto & 1) /* pad up to even number of bytes */ + seekto++; + if (!strncmp(wavechunk->wc_id, "fmt ", 4)) + { + long commblockonset = headersize + 8; + seekout = (long)lseek(fd, commblockonset, SEEK_SET); + if (seekout != commblockonset) + goto badheader; + if (read(fd, buf.b_c, sizeof(t_fmt)) < (int) sizeof(t_fmt)) + goto badheader; + nchannels = swap2(buf.b_fmt.f_nchannels, swap); + format = swap2(buf.b_fmt.f_nbitspersample, swap); + if (format == 16) + bytespersamp = 2; + else if (format == 24) + bytespersamp = 3; + else if (format == 32) + bytespersamp = 4; + else goto badheader; + samprate = swap4(buf.b_fmt.f_samplespersec, swap); + } + seekout = (long)lseek(fd, seekto, SEEK_SET); + if (seekout != seekto) + goto badheader; + if (read(fd, buf.b_c, sizeof(t_wavechunk)) < + (int) sizeof(t_wavechunk)) + goto badheader; + /* post("new chunk %c %c %c %c at %d", + wavechunk->wc_id[0], + wavechunk->wc_id[1], + wavechunk->wc_id[2], + wavechunk->wc_id[3], seekto); */ + headersize = (int)seekto; + } + bytelimit = swap4(wavechunk->wc_size, swap); + headersize += 8; + } + else + { + /* AIFF. same as WAVE; actually predates it. Disgusting. */ + t_datachunk *datachunk; + headersize = 12; + if (bytesread < 20) + goto badheader; + /* First we guess a number of channels, etc., in case there's + no COMM block to follow. */ + nchannels = 1; + bytespersamp = 2; + samprate = 44100; + /* copy the first chunk header to beginnning of buffer. */ + memcpy(buf.b_c, buf.b_c + headersize, sizeof(t_datachunk)); + /* read chunks in loop until we get to the data chunk */ + datachunk = &buf.b_datachunk; + while (strncmp(datachunk->dc_id, "SSND", 4)) + { + long chunksize = swap4(datachunk->dc_size, + swap), seekto = headersize + chunksize + 8, seekout; + if (seekto & 1) /* pad up to even number of bytes */ + seekto++; + /* post("chunk %c %c %c %c seek %d", + datachunk->dc_id[0], + datachunk->dc_id[1], + datachunk->dc_id[2], + datachunk->dc_id[3], seekto); */ + if (!strncmp(datachunk->dc_id, "COMM", 4)) + { + long commblockonset = headersize + 8; + t_comm *commchunk; + seekout = (long)lseek(fd, commblockonset, SEEK_SET); + if (seekout != commblockonset) + goto badheader; + if (read(fd, buf.b_c, sizeof(t_comm)) < + (int) sizeof(t_comm)) + goto badheader; + commchunk = &buf.b_commchunk; + nchannels = swap2(commchunk->c_nchannels, swap); + format = swap2(commchunk->c_bitspersamp, swap); + if (format == 16) + bytespersamp = 2; + else if (format == 24) + bytespersamp = 3; + else goto badheader; + samprate = readaiffsamprate((char *)commchunk->c_samprate, swap); + } + seekout = (long)lseek(fd, seekto, SEEK_SET); + if (seekout != seekto) + goto badheader; + if (read(fd, buf.b_c, sizeof(t_datachunk)) < + (int) sizeof(t_datachunk)) + goto badheader; + headersize = (int)seekto; + } + bytelimit = swap4(datachunk->dc_size, swap) - 8; + headersize += sizeof(t_datachunk); + } + } + /* seek past header and any sample frames to skip */ + sysrtn = (long)lseek(fd, + ((off_t)nchannels) * bytespersamp * skipframes + headersize, 0); + if (sysrtn != nchannels * bytespersamp * skipframes + headersize) + return (-1); + bytelimit -= nchannels * bytespersamp * skipframes; + if (bytelimit < 0) + bytelimit = 0; + /* copy sample format back to caller */ + p_info->headersize = headersize; + p_info->bigendian = bigendian; + p_info->channels = nchannels; + p_info->bytespersample = bytespersamp; + p_info->bytelimit = bytelimit; + p_info->samplerate = samprate; + return (fd); +badheader: + /* the header wasn't recognized. We're threadable here so let's not + print out the error... */ + errno = EIO; + return (-1); +} + + /* open a soundfile, using open_via_path(). This is used by readsf~ in + a not-perfectly-threadsafe way. LATER replace with a thread-hardened + version of open_soundfile_via_canvas() */ +int open_soundfile(const char *dirname, const char *filename, + t_soundfile_info *p_info, long skipframes) +{ + char buf[OBUFSIZE], *bufptr; + int fd, sf_fd; + fd = open_via_path(dirname, filename, "", buf, &bufptr, MAXPDSTRING, 1); + if (fd < 0) + return (-1); + sf_fd = open_soundfile_via_fd(fd, p_info, skipframes); + if (sf_fd < 0) + sys_close(fd); + return (sf_fd); +} + + /* open a soundfile, using open_via_canvas(). This is used by readsf~ in + a not-perfectly-threadsafe way. LATER replace with a thread-hardened + version of open_soundfile_via_canvas() */ +int open_soundfile_via_canvas(t_canvas *canvas, const char *filename, + t_soundfile_info *p_info, long skipframes) +{ + char buf[OBUFSIZE], *bufptr; + int fd, sf_fd; + fd = canvas_open(canvas, filename, "", buf, &bufptr, MAXPDSTRING, 1); + if (fd < 0) + return (-1); + sf_fd = open_soundfile_via_fd(fd, p_info, skipframes); + if (sf_fd < 0) + sys_close(fd); + return (sf_fd); +} + +static void soundfile_xferin_sample(int sfchannels, int nvecs, t_sample **vecs, + long itemsread, unsigned char *buf, int nitems, int bytespersamp, + int bigendian) +{ + int i, j; + unsigned char *sp, *sp2; + t_sample *fp; + int nchannels = (sfchannels < nvecs ? sfchannels : nvecs); + int bytesperframe = bytespersamp * sfchannels; + for (i = 0, sp = buf; i < nchannels; i++, sp += bytespersamp) + { + if (bytespersamp == 2) + { + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *fp = SCALE * ((sp2[0] << 24) | (sp2[1] << 16)); + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *fp = SCALE * ((sp2[1] << 24) | (sp2[0] << 16)); + } + } + else if (bytespersamp == 3) + { + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *fp = SCALE * ((sp2[0] << 24) | (sp2[1] << 16) + | (sp2[2] << 8)); + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *fp = SCALE * ((sp2[2] << 24) | (sp2[1] << 16) + | (sp2[0] << 8)); + } + } + else if (bytespersamp == 4) + { + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *(long *)fp = ((sp2[0] << 24) | (sp2[1] << 16) + | (sp2[2] << 8) | sp2[3]); + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *(long *)fp = ((sp2[3] << 24) | (sp2[2] << 16) + | (sp2[1] << 8) | sp2[0]); + } + } + } + /* zero out other outputs */ + for (i = sfchannels; i < nvecs; i++) + for (j = nitems, fp = vecs[i]; j--; ) + *fp++ = 0; + +} + +static void soundfile_xferin_words(int sfchannels, int nvecs, t_word **vecs, + long itemsread, unsigned char *buf, long nitems, int bytespersamp, + int bigendian) +{ + int i; + long j; + unsigned char *sp, *sp2; + t_word *wp; + int nchannels = (sfchannels < nvecs ? sfchannels : nvecs); + int bytesperframe = bytespersamp * sfchannels; + union + { + long long32; + float float32; + } word32; + for (i = 0, sp = buf; i < nchannels; i++, sp += bytespersamp) + { + if (bytespersamp == 2) + { + if (bigendian) + { + for (j = 0, sp2 = sp, wp = vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, wp++) + wp->w_float = SCALE * ((sp2[0] << 24) | (sp2[1] << 16)); + } + else + { + for (j = 0, sp2 = sp, wp = vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, wp++) + wp->w_float = SCALE * ((sp2[1] << 24) | (sp2[0] << 16)); + } + } + else if (bytespersamp == 3) + { + if (bigendian) + { + for (j = 0, sp2 = sp, wp = vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, wp++) + wp->w_float = SCALE * ((sp2[0] << 24) | (sp2[1] << 16) + | (sp2[2] << 8)); + } + else + { + for (j = 0, sp2 = sp, wp = vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, wp++) + wp->w_float = SCALE * ((sp2[2] << 24) | (sp2[1] << 16) + | (sp2[0] << 8)); + } + } + else if (bytespersamp == 4) + { + if (bigendian) + { + for (j = 0, sp2 = sp, wp = vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, wp++) + { + word32.long32 = (sp2[0] << 24) | + (sp2[1] << 16) | (sp2[2] << 8) | sp2[3]; + wp->w_float = word32.float32; + } + } + else + { + for (j = 0, sp2 = sp, wp = vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, wp++) + { + word32.long32 = (sp2[3] << 24) | + (sp2[2] << 16) | (sp2[1] << 8) | sp2[0]; + wp->w_float = word32.float32; + } + } + } + } + /* zero out other outputs */ + for (i = sfchannels; i < nvecs; i++) + for (j = nitems, wp = vecs[i]; j--; ) + (wp++)->w_float = 0; + +} + + /* soundfiler_write ... + + usage: write [flags] filename table ... + flags: + -nframes + -skip + -bytes + -normalize + -nextstep + -wave + -big + -little + */ + + /* the routine which actually does the work should LATER also be called + from garray_write16. */ + + + /* Parse arguments for writing. The "obj" argument is only for flagging + errors. For streaming to a file the "normalize", "onset" and "nframes" + arguments shouldn't be set but the calling routine flags this. */ + +static int soundfiler_writeargparse(void *obj, int *p_argc, t_atom **p_argv, + t_symbol **p_filesym, + int *p_filetype, int *p_bytespersamp, int *p_swap, int *p_bigendian, + int *p_normalize, long *p_onset, long *p_nframes, t_float *p_rate) +{ + int argc = *p_argc; + t_atom *argv = *p_argv; + int bytespersamp = 2, bigendian = 0, + endianness = -1, swap, filetype = -1, normalize = 0; + long onset = 0, nframes = 0x7fffffff; + t_symbol *filesym; + t_float rate = -1; + + while (argc > 0 && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + char *flag = argv->a_w.w_symbol->s_name + 1; + if (!strcmp(flag, "skip")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((onset = argv[1].a_w.w_float) < 0)) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "nframes")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((nframes = argv[1].a_w.w_float) < 0)) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "bytes")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((bytespersamp = argv[1].a_w.w_float) < 2) || + bytespersamp > 4) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "normalize")) + { + normalize = 1; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "wave")) + { + filetype = FORMAT_WAVE; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "nextstep")) + { + filetype = FORMAT_NEXT; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "aiff")) + { + filetype = FORMAT_AIFF; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "big")) + { + endianness = 1; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "little")) + { + endianness = 0; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "r") || !strcmp(flag, "rate")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((rate = argv[1].a_w.w_float) <= 0)) + goto usage; + argc -= 2; argv += 2; + } + else goto usage; + } + if (!argc || argv->a_type != A_SYMBOL) + goto usage; + filesym = argv->a_w.w_symbol; + + /* check if format not specified and fill in */ + if (filetype < 0) + { + if (strlen(filesym->s_name) >= 5 && + (!strcmp(filesym->s_name + strlen(filesym->s_name) - 4, ".aif") || + !strcmp(filesym->s_name + strlen(filesym->s_name) - 4, ".AIF"))) + filetype = FORMAT_AIFF; + if (strlen(filesym->s_name) >= 6 && + (!strcmp(filesym->s_name + strlen(filesym->s_name) - 5, ".aiff") || + !strcmp(filesym->s_name + strlen(filesym->s_name) - 5, ".AIFF"))) + filetype = FORMAT_AIFF; + if (strlen(filesym->s_name) >= 5 && + (!strcmp(filesym->s_name + strlen(filesym->s_name) - 4, ".snd") || + !strcmp(filesym->s_name + strlen(filesym->s_name) - 4, ".SND"))) + filetype = FORMAT_NEXT; + if (strlen(filesym->s_name) >= 4 && + (!strcmp(filesym->s_name + strlen(filesym->s_name) - 3, ".au") || + !strcmp(filesym->s_name + strlen(filesym->s_name) - 3, ".AU"))) + filetype = FORMAT_NEXT; + if (filetype < 0) + filetype = FORMAT_WAVE; + } + /* don't handle AIFF floating point samples */ + if (bytespersamp == 4) + { + if (filetype == FORMAT_AIFF) + { + pd_error(obj, "AIFF floating-point file format unavailable"); + goto usage; + } + } + /* for WAVE force little endian; for nextstep use machine native */ + if (filetype == FORMAT_WAVE) + { + bigendian = 0; + if (endianness == 1) + pd_error(obj, "WAVE file forced to little endian"); + } + else if (filetype == FORMAT_AIFF) + { + bigendian = 1; + if (endianness == 0) + pd_error(obj, "AIFF file forced to big endian"); + } + else if (endianness == -1) + { + bigendian = garray_ambigendian(); + } + else bigendian = endianness; + swap = (bigendian != garray_ambigendian()); + + argc--; argv++; + + *p_argc = argc; + *p_argv = argv; + *p_filesym = filesym; + *p_filetype = filetype; + *p_bytespersamp = bytespersamp; + *p_swap = swap; + *p_normalize = normalize; + *p_onset = onset; + *p_nframes = nframes; + *p_bigendian = bigendian; + *p_rate = rate; + return (0); +usage: + return (-1); +} + +/* p_headersize is a getter, set to NULL if not needed */ +static int create_soundfile(t_canvas *canvas, const char *filename, + int filetype, long nframes, int bytespersamp, int bigendian, int nchannels, + int swap, t_float samplerate, int *p_headersize) +{ + char filenamebuf[MAXPDSTRING], buf2[MAXPDSTRING]; + char headerbuf[WRITEHDRSIZE]; + t_wave *wavehdr = (t_wave *)headerbuf; + t_nextstep *nexthdr = (t_nextstep *)headerbuf; + t_aiff *aiffhdr = (t_aiff *)headerbuf; + int fd, headersize = 0; + + strncpy(filenamebuf, filename, MAXPDSTRING-10); + filenamebuf[MAXPDSTRING-10] = 0; + + if (filetype == FORMAT_NEXT) + { + if (strcmp(filenamebuf + strlen(filenamebuf)-4, ".snd")) + strcat(filenamebuf, ".snd"); + if (bigendian) + strncpy(nexthdr->ns_fileid, ".snd", 4); + else strncpy(nexthdr->ns_fileid, "dns.", 4); + nexthdr->ns_onset = swap4(sizeof(*nexthdr), swap); + nexthdr->ns_length = 0; + nexthdr->ns_format = swap4((bytespersamp == 3 ? NS_FORMAT_LINEAR_24 : + (bytespersamp == 4 ? NS_FORMAT_FLOAT : NS_FORMAT_LINEAR_16)), swap); + nexthdr->ns_sr = swap4(samplerate, swap); + nexthdr->ns_nchans = swap4(nchannels, swap); + strcpy(nexthdr->ns_info, "Pd "); + swapstring(nexthdr->ns_info, swap); + headersize = sizeof(t_nextstep); + } + else if (filetype == FORMAT_AIFF) + { + long datasize = nframes * nchannels * bytespersamp; + long longtmp; + if (strcmp(filenamebuf + strlen(filenamebuf)-4, ".aif") && + strcmp(filenamebuf + strlen(filenamebuf)-5, ".aiff")) + strcat(filenamebuf, ".aif"); + strncpy(aiffhdr->a_fileid, "FORM", 4); + aiffhdr->a_chunksize = swap4((uint32_t)(datasize + sizeof(*aiffhdr) + 4), swap); + strncpy(aiffhdr->a_aiffid, "AIFF", 4); + strncpy(aiffhdr->a_fmtid, "COMM", 4); + aiffhdr->a_fmtchunksize = swap4(18, swap); + aiffhdr->a_nchannels = swap2(nchannels, swap); + longtmp = swap4((uint32_t)nframes, swap); + memcpy(&aiffhdr->a_nframeshi, &longtmp, 4); + aiffhdr->a_bitspersamp = swap2(8 * bytespersamp, swap); + makeaiffsamprate(samplerate, aiffhdr->a_samprate); + strncpy(((char *)(&aiffhdr->a_samprate))+10, "SSND", 4); + longtmp = swap4((uint32_t)(datasize + 8), swap); + memcpy(((char *)(&aiffhdr->a_samprate))+14, &longtmp, 4); + memset(((char *)(&aiffhdr->a_samprate))+18, 0, 8); + headersize = AIFFPLUS; + } + else /* WAVE format */ + { + long datasize = nframes * nchannels * bytespersamp; + if (strcmp(filenamebuf + strlen(filenamebuf)-4, ".wav")) + strcat(filenamebuf, ".wav"); + strncpy(wavehdr->w_fileid, "RIFF", 4); + wavehdr->w_chunksize = swap4((uint32_t)(datasize + sizeof(*wavehdr) - 8), swap); + strncpy(wavehdr->w_waveid, "WAVE", 4); + strncpy(wavehdr->w_fmtid, "fmt ", 4); + wavehdr->w_fmtchunksize = swap4(16, swap); + wavehdr->w_fmttag = + swap2((bytespersamp == 4 ? WAV_FLOAT : WAV_INT), swap); + wavehdr->w_nchannels = swap2(nchannels, swap); + wavehdr->w_samplespersec = swap4(samplerate, swap); + wavehdr->w_navgbytespersec = + swap4((int)(samplerate * nchannels * bytespersamp), swap); + wavehdr->w_nblockalign = swap2(nchannels * bytespersamp, swap); + wavehdr->w_nbitspersample = swap2(8 * bytespersamp, swap); + strncpy(wavehdr->w_datachunkid, "data", 4); + wavehdr->w_datachunksize = swap4((uint32_t)datasize, swap); + headersize = sizeof(t_wave); + } + + canvas_makefilename(canvas, filenamebuf, buf2, MAXPDSTRING); + if ((fd = sys_open(buf2, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) + return (-1); + + if (write(fd, headerbuf, headersize) < headersize) + { + close (fd); + return (-1); + } + if(p_headersize) + *p_headersize = headersize; + return (fd); +} + +static void soundfile_finishwrite(void *obj, char *filename, int fd, + int filetype, long nframes, long itemswritten, int bytesperframe, int swap) +{ + if (itemswritten < nframes) + { + if (nframes < 0x7fffffff) + pd_error(obj, "soundfiler_write: %ld out of %ld bytes written", + itemswritten, nframes); + /* try to fix size fields in header */ + if (filetype == FORMAT_WAVE) + { + long datasize = itemswritten * bytesperframe, mofo; + + if (lseek(fd, + ((char *)(&((t_wave *)0)->w_chunksize)) - (char *)0, + SEEK_SET) == 0) + goto baddonewrite; + mofo = swap4((uint32_t)(datasize + sizeof(t_wave) - 8), swap); + if (write(fd, (char *)(&mofo), 4) < 4) + goto baddonewrite; + if (lseek(fd, + ((char *)(&((t_wave *)0)->w_datachunksize)) - (char *)0, + SEEK_SET) == 0) + goto baddonewrite; + mofo = swap4((uint32_t)datasize, swap); + if (write(fd, (char *)(&mofo), 4) < 4) + goto baddonewrite; + } + if (filetype == FORMAT_AIFF) + { + long mofo; + if (lseek(fd, + ((char *)(&((t_aiff *)0)->a_nframeshi)) - (char *)0, + SEEK_SET) == 0) + goto baddonewrite; + mofo = swap4((uint32_t)itemswritten, swap); + if (write(fd, (char *)(&mofo), 4) < 4) + goto baddonewrite; + if (lseek(fd, + ((char *)(&((t_aiff *)0)->a_chunksize)) - (char *)0, + SEEK_SET) == 0) + goto baddonewrite; + mofo = swap4((uint32_t)(itemswritten*bytesperframe+AIFFHDRSIZE), swap); + if (write(fd, (char *)(&mofo), 4) < 4) + goto baddonewrite; + if (lseek(fd, (AIFFHDRSIZE+4), SEEK_SET) == 0) + goto baddonewrite; + mofo = swap4((uint32_t)(itemswritten*bytesperframe), swap); + if (write(fd, (char *)(&mofo), 4) < 4) + goto baddonewrite; + } + if (filetype == FORMAT_NEXT) + { + /* do it the lazy way: just set the size field to 'unknown size'*/ + uint32_t nextsize = 0xffffffff; + if (lseek(fd, 8, SEEK_SET) == 0) + { + goto baddonewrite; + } + if (write(fd, &nextsize, 4) < 4) + { + goto baddonewrite; + } + } + } + return; +baddonewrite: + post("%s: %s", filename, strerror(errno)); +} + +static void soundfile_xferout_sample(int nchannels, t_sample **vecs, + unsigned char *buf, int nitems, long onset, int bytespersamp, + int bigendian, t_sample normalfactor) +{ + int i, j; + unsigned char *sp, *sp2; + t_sample *fp; + int bytesperframe = bytespersamp * nchannels; + for (i = 0, sp = buf; i < nchannels; i++, sp += bytespersamp) + { + if (bytespersamp == 2) + { + t_sample ff = normalfactor * 32768.; + if (bigendian) + { + for (j = 0, sp2 = sp, fp = vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + int xx = 32768. + (*fp * ff); + xx -= 32768; + if (xx < -32767) + xx = -32767; + if (xx > 32767) + xx = 32767; + sp2[0] = (xx >> 8); + sp2[1] = xx; + } + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + int xx = 32768. + (*fp * ff); + xx -= 32768; + if (xx < -32767) + xx = -32767; + if (xx > 32767) + xx = 32767; + sp2[1] = (xx >> 8); + sp2[0] = xx; + } + } + } + else if (bytespersamp == 3) + { + t_sample ff = normalfactor * 8388608.; + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + int xx = 8388608. + (*fp * ff); + xx -= 8388608; + if (xx < -8388607) + xx = -8388607; + if (xx > 8388607) + xx = 8388607; + sp2[0] = (xx >> 16); + sp2[1] = (xx >> 8); + sp2[2] = xx; + } + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + int xx = 8388608. + (*fp * ff); + xx -= 8388608; + if (xx < -8388607) + xx = -8388607; + if (xx > 8388607) + xx = 8388607; + sp2[2] = (xx >> 16); + sp2[1] = (xx >> 8); + sp2[0] = xx; + } + } + } + else if (bytespersamp == 4) + { + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + t_sampleuint f2; + f2.f = *fp * normalfactor; + sp2[0] = (f2.l >> 24); sp2[1] = (f2.l >> 16); + sp2[2] = (f2.l >> 8); sp2[3] = f2.l; + } + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + t_sampleuint f2; + f2.f = *fp * normalfactor; + sp2[3] = (f2.l >> 24); sp2[2] = (f2.l >> 16); + sp2[1] = (f2.l >> 8); sp2[0] = f2.l; + } + } + } + } +} + +static void soundfile_xferout_words(int nchannels, t_word **vecs, + unsigned char *buf, long nitems, long onset, int bytespersamp, + int bigendian, t_sample normalfactor) +{ + int i, j; + unsigned char *sp, *sp2; + t_word *wp; + int bytesperframe = bytespersamp * nchannels; + for (i = 0, sp = buf; i < nchannels; i++, sp += bytespersamp) + { + if (bytespersamp == 2) + { + t_sample ff = normalfactor * 32768.; + if (bigendian) + { + for (j = 0, sp2 = sp, wp = vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, wp++) + { + int xx = 32768. + (wp->w_float * ff); + xx -= 32768; + if (xx < -32767) + xx = -32767; + if (xx > 32767) + xx = 32767; + sp2[0] = (xx >> 8); + sp2[1] = xx; + } + } + else + { + for (j = 0, sp2 = sp, wp = vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, wp++) + { + int xx = 32768. + (wp->w_float * ff); + xx -= 32768; + if (xx < -32767) + xx = -32767; + if (xx > 32767) + xx = 32767; + sp2[1] = (xx >> 8); + sp2[0] = xx; + } + } + } + else if (bytespersamp == 3) + { + t_sample ff = normalfactor * 8388608.; + if (bigendian) + { + for (j = 0, sp2 = sp, wp = vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, wp++) + { + int xx = 8388608. + (wp->w_float * ff); + xx -= 8388608; + if (xx < -8388607) + xx = -8388607; + if (xx > 8388607) + xx = 8388607; + sp2[0] = (xx >> 16); + sp2[1] = (xx >> 8); + sp2[2] = xx; + } + } + else + { + for (j = 0, sp2 = sp, wp = vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, wp++) + { + int xx = 8388608. + (wp->w_float * ff); + xx -= 8388608; + if (xx < -8388607) + xx = -8388607; + if (xx > 8388607) + xx = 8388607; + sp2[2] = (xx >> 16); + sp2[1] = (xx >> 8); + sp2[0] = xx; + } + } + } + else if (bytespersamp == 4) + { + if (bigendian) + { + for (j = 0, sp2 = sp, wp = vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, wp++) + { + t_sampleuint f2; + f2.f = wp->w_float * normalfactor; + sp2[0] = (f2.l >> 24); sp2[1] = (f2.l >> 16); + sp2[2] = (f2.l >> 8); sp2[3] = f2.l; + } + } + else + { + for (j = 0, sp2 = sp, wp = vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, wp++) + { + t_sampleuint f2; + f2.f = wp->w_float * normalfactor; + sp2[3] = (f2.l >> 24); sp2[2] = (f2.l >> 16); + sp2[1] = (f2.l >> 8); sp2[0] = f2.l; + } + } + } + } +} + +/* ------- soundfiler - reads and writes soundfiles to/from "garrays" ---- */ +#define DEFMAXSIZE 4000000 /* default maximum 16 MB per channel */ +#define SAMPBUFSIZE 1024 + + +static t_class *soundfiler_class; + +typedef struct _soundfiler +{ + t_object x_obj; + t_outlet *x_out2; + t_canvas *x_canvas; +} t_soundfiler; + +static t_soundfiler *soundfiler_new(void) +{ + t_soundfiler *x = (t_soundfiler *)pd_new(soundfiler_class); + x->x_canvas = canvas_getcurrent(); + outlet_new(&x->x_obj, &s_float); + x->x_out2 = outlet_new(&x->x_obj, &s_float); + return (x); +} + + /* soundfiler_read ... + + usage: read [flags] filename table ... + flags: + -skip ... frames to skip in file + -onset ... onset in table to read into (NOT DONE YET) + -raw + -resize + -maxsize + */ + +static void soundfiler_read(t_soundfiler *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_soundfile_info info; + int resize = 0, i; + long skipframes = 0, finalsize = 0, itemsleft, + maxsize = DEFMAXSIZE, itemsread = 0, j; + int fd = -1; + char endianness, *filename; + t_garray *garrays[MAXSFCHANS]; + t_word *vecs[MAXSFCHANS]; + char sampbuf[SAMPBUFSIZE]; + int bufframes; + long nitems; + FILE *fp; + info.samplerate = 0, + info.channels = 0, + info.bytespersample = 0, + info.headersize = -1, + info.bigendian = 0, + info.bytelimit = 0x7fffffff; + while (argc > 0 && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + char *flag = argv->a_w.w_symbol->s_name + 1; + if (!strcmp(flag, "skip")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((skipframes = argv[1].a_w.w_float) < 0)) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "raw")) + { + if (argc < 5 || + argv[1].a_type != A_FLOAT || + ((info.headersize = argv[1].a_w.w_float) < 0) || + argv[2].a_type != A_FLOAT || + ((info.channels = argv[2].a_w.w_float) < 1) || + (info.channels > MAXSFCHANS) || + argv[3].a_type != A_FLOAT || + ((info.bytespersample = argv[3].a_w.w_float) < 2) || + (info.bytespersample > 4) || + argv[4].a_type != A_SYMBOL || + ((endianness = argv[4].a_w.w_symbol->s_name[0]) != 'b' + && endianness != 'l' && endianness != 'n')) + goto usage; + if (endianness == 'b') + info.bigendian = 1; + else if (endianness == 'l') + info.bigendian = 0; + else + info.bigendian = garray_ambigendian(); + info.samplerate = sys_getsr(); + argc -= 5; argv += 5; + } + else if (!strcmp(flag, "resize")) + { + resize = 1; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "maxsize")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((maxsize = argv[1].a_w.w_float) < 0)) + goto usage; + resize = 1; /* maxsize implies resize. */ + argc -= 2; argv += 2; + } + else goto usage; + } + if (argc < 2 || argc > MAXSFCHANS + 1 || argv[0].a_type != A_SYMBOL) + goto usage; + filename = argv[0].a_w.w_symbol->s_name; + argc--; argv++; + + for (i = 0; i < argc; i++) + { + int vecsize; + if (argv[i].a_type != A_SYMBOL) + goto usage; + if (!(garrays[i] = + (t_garray *)pd_findbyclass(argv[i].a_w.w_symbol, garray_class))) + { + pd_error(x, "%s: no such table", argv[i].a_w.w_symbol->s_name); + goto done; + } + else if (!garray_getfloatwords(garrays[i], &vecsize, + &vecs[i])) + error("%s: bad template for tabwrite", + argv[i].a_w.w_symbol->s_name); + if (finalsize && finalsize != vecsize && !resize) + { + post("soundfiler_read: arrays have different lengths; resizing..."); + resize = 1; + } + finalsize = vecsize; + } + fd = open_soundfile_via_canvas(x->x_canvas, filename, &info, skipframes); + + if (fd < 0) + { + pd_error(x, "soundfiler_read: %s: %s", filename, (errno == EIO ? + "unknown or bad header format" : strerror(errno))); + goto done; + } + + if (resize) + { + /* figure out what to resize to */ + long poswas, eofis, framesinfile; + + poswas = (long)lseek(fd, 0, SEEK_CUR); + eofis = (long)lseek(fd, 0, SEEK_END); + if (poswas < 0 || eofis < 0 || eofis < poswas) + { + pd_error(x, "soundfiler_read: lseek failed"); + goto done; + } + lseek(fd, poswas, SEEK_SET); + framesinfile = (eofis - poswas) / (info.channels * info.bytespersample); + if (framesinfile > maxsize) + { + pd_error(x, "soundfiler_read: truncated to %ld elements", maxsize); + framesinfile = maxsize; + } + if (framesinfile > info.bytelimit / (info.channels * info.bytespersample)) + framesinfile = info.bytelimit / (info.channels * info.bytespersample); + finalsize = framesinfile; + for (i = 0; i < argc; i++) + { + int vecsize; + + garray_resize_long(garrays[i], finalsize); + /* for sanity's sake let's clear the save-in-patch flag here */ + garray_setsaveit(garrays[i], 0); + if (!garray_getfloatwords(garrays[i], &vecsize, &vecs[i]) + /* if the resize failed, garray_resize reported the error */ + || (vecsize != framesinfile)) + { + pd_error(x, "resize failed"); + goto done; + } + } + } + if (!finalsize) finalsize = 0x7fffffff; + if (finalsize > info.bytelimit / (info.channels * info.bytespersample)) + finalsize = info.bytelimit / (info.channels * info.bytespersample); + fp = fdopen(fd, "rb"); + bufframes = SAMPBUFSIZE / (info.channels * info.bytespersample); + + for (itemsread = 0; itemsread < finalsize; ) + { + long thisread = finalsize - itemsread; + thisread = (thisread > bufframes ? bufframes : thisread); + nitems = fread(sampbuf, info.channels * info.bytespersample, thisread, fp); + if (nitems <= 0) break; + soundfile_xferin_words(info.channels, argc, vecs, itemsread, + (unsigned char *)sampbuf, nitems, info.bytespersample, info.bigendian); + itemsread += nitems; + } + /* zero out remaining elements of vectors */ + + for (i = 0; i < argc; i++) + { + int nzero, vecsize; + if (garray_getfloatwords(garrays[i], &vecsize, &vecs[i])) + for (j = itemsread; j < vecsize; j++) + vecs[i][j].w_float = 0; + } + /* zero out vectors in excess of number of channels */ + for (i = info.channels; i < argc; i++) + { + int vecsize; + t_word *foo; + if (garray_getfloatwords(garrays[i], &vecsize, &foo)) + for (j = 0; j < vecsize; j++) + foo[j].w_float = 0; + } + /* do all graphics updates */ + for (i = 0; i < argc; i++) + garray_redraw(garrays[i]); + fclose(fp); + fd = -1; + goto done; +usage: + pd_error(x, "usage: read [flags] filename tablename..."); + post("flags: -skip -resize -maxsize ..."); + post("-raw ."); +done: + if (fd >= 0) + close (fd); + outlet_soundfile_info(x->x_out2, &info); + outlet_float(x->x_obj.ob_outlet, (t_float)itemsread); +} + + /* this is broken out from soundfiler_write below so garray_write can + call it too... not done yet though. */ + +long soundfiler_dowrite(void *obj, t_canvas *canvas, + int argc, t_atom *argv, t_soundfile_info *info) +{ + int endianness, swap, filetype, normalize, i; + long onset, nframes, itemsleft, + maxsize = DEFMAXSIZE, itemswritten = 0, j; + t_garray *garrays[MAXSFCHANS]; + t_word *vectors[MAXSFCHANS]; + char sampbuf[SAMPBUFSIZE]; + int bufframes, nitems; + int fd = -1; + t_sample normfactor, biggest = 0; + t_float samplerate; + t_symbol *filesym; + + if (soundfiler_writeargparse(obj, &argc, &argv, &filesym, &filetype, + &info->bytespersample, &swap, &info->bigendian, &normalize, &onset, &nframes, + &samplerate)) + goto usage; + info->channels = argc; + if (info->channels < 1 || info->channels > MAXSFCHANS) + goto usage; + if (samplerate < 0) + info->samplerate = sys_getsr(); + else + info->samplerate = (int)samplerate; + for (i = 0; i < info->channels; i++) + { + int vecsize; + if (argv[i].a_type != A_SYMBOL) + goto usage; + if (!(garrays[i] = + (t_garray *)pd_findbyclass(argv[i].a_w.w_symbol, garray_class))) + { + pd_error(obj, "%s: no such table", argv[i].a_w.w_symbol->s_name); + goto fail; + } + else if (!garray_getfloatwords(garrays[i], &vecsize, &vectors[i])) + error("%s: bad template for tabwrite", + argv[i].a_w.w_symbol->s_name); + if (nframes > vecsize - onset) + nframes = vecsize - onset; + } + if (nframes <= 0) + { + pd_error(obj, "soundfiler_write: no samples at onset %ld", onset); + goto fail; + } + for (i = 0; i < info->channels; i++) /* find biggest sample for normalizing */ + { + for (j = onset; j < nframes + onset; j++) + { + if (vectors[i][j].w_float > biggest) + biggest = vectors[i][j].w_float; + else if (-vectors[i][j].w_float > biggest) + biggest = -vectors[i][j].w_float; + } + } + if ((fd = create_soundfile(canvas, filesym->s_name, filetype, + nframes, info->bytespersample, info->bigendian, info->channels, + swap, info->samplerate, &info->headersize)) < 0) + { + post("%s: %s\n", filesym->s_name, strerror(errno)); + goto fail; + } + if (!normalize) + { + if ((info->bytespersample != 4) && (biggest > 1)) + { + post("%s: reducing max amplitude %f to 1", + filesym->s_name, biggest); + normalize = 1; + } + else post("%s: biggest amplitude = %f", filesym->s_name, biggest); + } + if (normalize) + normfactor = (biggest > 0 ? 32767./(32768. * biggest) : 1); + else normfactor = 1; + + bufframes = SAMPBUFSIZE / (info->channels * info->bytespersample); + + for (itemswritten = 0; itemswritten < nframes; ) + { + long thiswrite = nframes - itemswritten, nitems, nbytes; + thiswrite = (thiswrite > bufframes ? bufframes : thiswrite); + soundfile_xferout_words(argc, vectors, (unsigned char *)sampbuf, + thiswrite, onset, info->bytespersample, info->bigendian, normfactor); + nbytes = write(fd, sampbuf, info->channels * info->bytespersample * thiswrite); + if (nbytes < info->channels * info->bytespersample * thiswrite) + { + post("%s: %s", filesym->s_name, strerror(errno)); + if (nbytes > 0) + itemswritten += nbytes / (info->channels * info->bytespersample); + break; + } + itemswritten += thiswrite; + onset += thiswrite; + } + if (fd >= 0) + { + soundfile_finishwrite(obj, filesym->s_name, fd, + filetype, nframes, itemswritten, info->channels * info->bytespersample, swap); + close (fd); + } + return ((float)itemswritten); +usage: + pd_error(obj, "usage: write [flags] filename tablename..."); + post("flags: -skip -nframes -bytes -wave -aiff -nextstep ..."); + post("-big -little -normalize"); + post("(defaults to a 16-bit wave file)."); +fail: + if (fd >= 0) + close (fd); + return (0); +} + +static void soundfiler_write(t_soundfiler *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_soundfile_info info; + long bozo; + info.samplerate = 0, + info.channels = 0, + info.bytespersample = 0, + info.headersize = -1, + info.bigendian = 0, + info.bytelimit = 0x7fffffff; + bozo = soundfiler_dowrite(x, x->x_canvas, argc, argv, &info); + outlet_soundfile_info(x->x_out2, &info); + outlet_float(x->x_obj.ob_outlet, (t_float)bozo); +} + +static void soundfiler_setup(void) +{ + soundfiler_class = class_new(gensym("soundfiler"), (t_newmethod)soundfiler_new, + 0, sizeof(t_soundfiler), 0, 0); + class_addmethod(soundfiler_class, (t_method)soundfiler_read, gensym("read"), + A_GIMME, 0); + class_addmethod(soundfiler_class, (t_method)soundfiler_write, + gensym("write"), A_GIMME, 0); +} + + +/************************* readsf object ******************************/ + +/* READSF uses the Posix threads package; for the moment we're Linux +only although this should be portable to the other platforms. + +Each instance of readsf~ owns a "child" thread for doing the unix (MSW?) file +reading. The parent thread signals the child each time: + (1) a file wants opening or closing; + (2) we've eaten another 1/16 of the shared buffer (so that the + child thread should check if it's time to read some more.) +The child signals the parent whenever a read has completed. Signalling +is done by setting "conditions" and putting data in mutex-controlled common +areas. +*/ + +#define MAXBYTESPERSAMPLE 4 +#define MAXVECSIZE 128 + +#define READSIZE 65536 +#define WRITESIZE 65536 +#define DEFBUFPERCHAN 262144 +#define MINBUFSIZE (4 * READSIZE) +#define MAXBUFSIZE 16777216 /* arbitrary; just don't want to hang malloc */ + +#define REQUEST_NOTHING 0 +#define REQUEST_OPEN 1 +#define REQUEST_CLOSE 2 +#define REQUEST_QUIT 3 +#define REQUEST_BUSY 4 + +#define STATE_IDLE 0 +#define STATE_STARTUP 1 +#define STATE_STREAM 2 + +static t_class *readsf_class; + +typedef struct _readsf +{ + t_object x_obj; + t_canvas *x_canvas; + t_clock *x_clock; + char *x_buf; /* soundfile buffer */ + int x_bufsize; /* buffer size in bytes */ + int x_noutlets; /* number of audio outlets */ + t_sample *(x_outvec[MAXSFCHANS]); /* audio vectors */ + int x_vecsize; /* vector size for transfers */ + t_outlet *x_bangout; /* bang-on-done outlet */ + int x_state; /* opened, running, or idle */ + t_float x_insamplerate; /* sample rate of input signal if known */ + /* parameters to communicate with subthread */ + int x_requestcode; /* pending request from parent to I/O thread */ + char *x_filename; /* file to open (string is permanently allocated) */ + int x_fileerror; /* slot for "errno" return */ + int x_skipheaderbytes; /* size of header we'll skip */ + int x_bytespersample; /* bytes per sample (2 or 3) */ + int x_bigendian; /* true if file is big-endian */ + int x_sfchannels; /* number of channels in soundfile */ + t_float x_samplerate; /* sample rate of soundfile */ + long x_onsetframes; /* number of sample frames to skip */ + long x_bytelimit; /* max number of data bytes to read */ + int x_fd; /* filedesc */ + int x_fifosize; /* buffer size appropriately rounded down */ + int x_fifohead; /* index of next byte to get from file */ + int x_fifotail; /* index of next byte the ugen will read */ + int x_eof; /* true if fifohead has stopped changing */ + int x_sigcountdown; /* counter for signalling child for more data */ + int x_sigperiod; /* number of ticks per signal */ + int x_filetype; /* writesf~ only; type of file to create */ + int x_itemswritten; /* writesf~ only; items written */ + int x_swap; /* writesf~ only; true if byte swapping */ + t_float x_f; /* writesf~ only; scalar for signal inlet */ + pthread_mutex_t x_mutex; + pthread_cond_t x_requestcondition; + pthread_cond_t x_answercondition; + pthread_t x_childthread; +} t_readsf; + + +/************** the child thread which performs file I/O ***********/ + +#if 0 +static void pute(char *s) /* debug routine */ +{ + write(2, s, strlen(s)); +} +#define DEBUG_SOUNDFILE +#endif + +#if 1 +#define sfread_cond_wait pthread_cond_wait +#define sfread_cond_signal pthread_cond_signal +#else +#include /* debugging version... */ +#include +static void readsf_fakewait(pthread_mutex_t *b) +{ + struct timeval timout; + timout.tv_sec = 0; + timout.tv_usec = 1000000; + pthread_mutex_unlock(b); + select(0, 0, 0, 0, &timout); + pthread_mutex_lock(b); +} + +#define sfread_cond_wait(a,b) readsf_fakewait(b) +#define sfread_cond_signal(a) +#endif + +static void *readsf_child_main(void *zz) +{ + t_readsf *x = zz; +#ifdef DEBUG_SOUNDFILE + pute("1\n"); +#endif + pthread_mutex_lock(&x->x_mutex); + while (1) + { + int fd, fifohead; + char *buf; +#ifdef DEBUG_SOUNDFILE + pute("0\n"); +#endif + if (x->x_requestcode == REQUEST_NOTHING) + { +#ifdef DEBUG_SOUNDFILE + pute("wait 2\n"); +#endif + sfread_cond_signal(&x->x_answercondition); + sfread_cond_wait(&x->x_requestcondition, &x->x_mutex); +#ifdef DEBUG_SOUNDFILE + pute("3\n"); +#endif + } + else if (x->x_requestcode == REQUEST_OPEN) + { + char boo[80]; + long sysrtn, wantbytes; + + /* copy file stuff out of the data structure so we can + relinquish the mutex while we're in open_soundfile(). */ + t_soundfile_info info; + long onsetframes = x->x_onsetframes; + char *filename = x->x_filename; + char *dirname = canvas_getdir(x->x_canvas)->s_name; + info.samplerate = x->x_samplerate; + info.channels = x->x_sfchannels; + info.headersize = x->x_skipheaderbytes; + info.bytespersample = x->x_bytespersample; + info.bigendian = x->x_bigendian; + info.bytelimit = 0x7fffffff; +#ifdef DEBUG_SOUNDFILE + pute("4\n"); +#endif + /* alter the request code so that an ensuing "open" will get + noticed. */ + x->x_requestcode = REQUEST_BUSY; + x->x_fileerror = 0; + + /* if there's already a file open, close it */ + if (x->x_fd >= 0) + { + fd = x->x_fd; + pthread_mutex_unlock(&x->x_mutex); + close (fd); + pthread_mutex_lock(&x->x_mutex); + x->x_fd = -1; + if (x->x_requestcode != REQUEST_BUSY) + goto lost; + } + /* open the soundfile with the mutex unlocked */ + pthread_mutex_unlock(&x->x_mutex); + fd = open_soundfile(dirname, filename, &info, onsetframes); + pthread_mutex_lock(&x->x_mutex); + +#ifdef DEBUG_SOUNDFILE + pute("5\n"); +#endif + /* copy back into the instance structure. */ + x->x_bytespersample = info.bytespersample; + x->x_sfchannels = info.channels; + x->x_bigendian = info.bigendian; + x->x_fd = fd; + x->x_bytelimit = info.bytelimit; + if (fd < 0) + { + x->x_fileerror = errno; + x->x_eof = 1; +#ifdef DEBUG_SOUNDFILE + pute("open failed\n"); + pute(filename); + pute(dirname); +#endif + goto lost; + } + /* check if another request has been made; if so, field it */ + if (x->x_requestcode != REQUEST_BUSY) + goto lost; +#ifdef DEBUG_SOUNDFILE + pute("6\n"); +#endif + x->x_fifohead = 0; + /* set fifosize from bufsize. fifosize must be a + multiple of the number of bytes eaten for each DSP + tick. We pessimistically assume MAXVECSIZE samples + per tick since that could change. There could be a + problem here if the vector size increases while a + soundfile is being played... */ + x->x_fifosize = x->x_bufsize - (x->x_bufsize % + (x->x_bytespersample * x->x_sfchannels * MAXVECSIZE)); + /* arrange for the "request" condition to be signalled 16 + times per buffer */ +#ifdef DEBUG_SOUNDFILE + sprintf(boo, "fifosize %d\n", + x->x_fifosize); + pute(boo); +#endif + x->x_sigcountdown = x->x_sigperiod = + (x->x_fifosize / + (16 * x->x_bytespersample * x->x_sfchannels * + x->x_vecsize)); + /* in a loop, wait for the fifo to get hungry and feed it */ + + while (x->x_requestcode == REQUEST_BUSY) + { + int fifosize = x->x_fifosize; +#ifdef DEBUG_SOUNDFILE + pute("77\n"); +#endif + if (x->x_eof) + break; + if (x->x_fifohead >= x->x_fifotail) + { + /* if the head is >= the tail, we can immediately read + to the end of the fifo. Unless, that is, we would + read all the way to the end of the buffer and the + "tail" is zero; this would fill the buffer completely + which isn't allowed because you can't tell a completely + full buffer from an empty one. */ + if (x->x_fifotail || (fifosize - x->x_fifohead > READSIZE)) + { + wantbytes = fifosize - x->x_fifohead; + if (wantbytes > READSIZE) + wantbytes = READSIZE; + if (wantbytes > x->x_bytelimit) + wantbytes = x->x_bytelimit; +#ifdef DEBUG_SOUNDFILE + sprintf(boo, "head %d, tail %d, size %d\n", + x->x_fifohead, x->x_fifotail, wantbytes); + pute(boo); +#endif + } + else + { +#ifdef DEBUG_SOUNDFILE + pute("wait 7a ...\n"); +#endif + sfread_cond_signal(&x->x_answercondition); +#ifdef DEBUG_SOUNDFILE + pute("signalled\n"); +#endif + sfread_cond_wait(&x->x_requestcondition, + &x->x_mutex); +#ifdef DEBUG_SOUNDFILE + pute("7a done\n"); +#endif + continue; + } + } + else + { + /* otherwise check if there are at least READSIZE + bytes to read. If not, wait and loop back. */ + wantbytes = x->x_fifotail - x->x_fifohead - 1; + if (wantbytes < READSIZE) + { +#ifdef DEBUG_SOUNDFILE + pute("wait 7...\n"); +#endif + sfread_cond_signal(&x->x_answercondition); + sfread_cond_wait(&x->x_requestcondition, + &x->x_mutex); +#ifdef DEBUG_SOUNDFILE + pute("7 done\n"); +#endif + continue; + } + else wantbytes = READSIZE; + if (wantbytes > x->x_bytelimit) + wantbytes = x->x_bytelimit; + } +#ifdef DEBUG_SOUNDFILE + pute("8\n"); +#endif + fd = x->x_fd; + buf = x->x_buf; + fifohead = x->x_fifohead; + pthread_mutex_unlock(&x->x_mutex); + sysrtn = read(fd, buf + fifohead, wantbytes); + pthread_mutex_lock(&x->x_mutex); + if (x->x_requestcode != REQUEST_BUSY) + break; + if (sysrtn < 0) + { +#ifdef DEBUG_SOUNDFILE + pute("fileerror\n"); +#endif + x->x_fileerror = errno; + break; + } + else if (sysrtn == 0) + { + x->x_eof = 1; + break; + } + else + { + x->x_fifohead += sysrtn; + x->x_bytelimit -= sysrtn; + if (x->x_fifohead == fifosize) + x->x_fifohead = 0; + if (x->x_bytelimit <= 0) + { + x->x_eof = 1; + break; + } + } +#ifdef DEBUG_SOUNDFILE + sprintf(boo, "after: head %d, tail %d\n", + x->x_fifohead, x->x_fifotail); + pute(boo); +#endif + /* signal parent in case it's waiting for data */ + sfread_cond_signal(&x->x_answercondition); + } + lost: + + if (x->x_requestcode == REQUEST_BUSY) + x->x_requestcode = REQUEST_NOTHING; + /* fell out of read loop: close file if necessary, + set EOF and signal once more */ + if (x->x_fd >= 0) + { + fd = x->x_fd; + pthread_mutex_unlock(&x->x_mutex); + close (fd); + pthread_mutex_lock(&x->x_mutex); + x->x_fd = -1; + } + sfread_cond_signal(&x->x_answercondition); + + } + else if (x->x_requestcode == REQUEST_CLOSE) + { + if (x->x_fd >= 0) + { + fd = x->x_fd; + pthread_mutex_unlock(&x->x_mutex); + close (fd); + pthread_mutex_lock(&x->x_mutex); + x->x_fd = -1; + } + if (x->x_requestcode == REQUEST_CLOSE) + x->x_requestcode = REQUEST_NOTHING; + sfread_cond_signal(&x->x_answercondition); + } + else if (x->x_requestcode == REQUEST_QUIT) + { + if (x->x_fd >= 0) + { + fd = x->x_fd; + pthread_mutex_unlock(&x->x_mutex); + close (fd); + pthread_mutex_lock(&x->x_mutex); + x->x_fd = -1; + } + x->x_requestcode = REQUEST_NOTHING; + sfread_cond_signal(&x->x_answercondition); + break; + } + else + { +#ifdef DEBUG_SOUNDFILE + pute("13\n"); +#endif + } + } +#ifdef DEBUG_SOUNDFILE + pute("thread exit\n"); +#endif + pthread_mutex_unlock(&x->x_mutex); + return (0); +} + +/******** the object proper runs in the calling (parent) thread ****/ + +static void readsf_tick(t_readsf *x); + +static void *readsf_new(t_floatarg fnchannels, t_floatarg fbufsize) +{ + t_readsf *x; + int nchannels = fnchannels, bufsize = fbufsize, i; + char *buf; + + if (nchannels < 1) + nchannels = 1; + else if (nchannels > MAXSFCHANS) + nchannels = MAXSFCHANS; + if (bufsize <= 0) bufsize = DEFBUFPERCHAN * nchannels; + else if (bufsize < MINBUFSIZE) + bufsize = MINBUFSIZE; + else if (bufsize > MAXBUFSIZE) + bufsize = MAXBUFSIZE; + buf = getbytes(bufsize); + if (!buf) return (0); + + x = (t_readsf *)pd_new(readsf_class); + + for (i = 0; i < nchannels; i++) + outlet_new(&x->x_obj, gensym("signal")); + x->x_noutlets = nchannels; + x->x_bangout = outlet_new(&x->x_obj, &s_bang); + pthread_mutex_init(&x->x_mutex, 0); + pthread_cond_init(&x->x_requestcondition, 0); + pthread_cond_init(&x->x_answercondition, 0); + x->x_vecsize = MAXVECSIZE; + x->x_state = STATE_IDLE; + x->x_clock = clock_new(x, (t_method)readsf_tick); + x->x_canvas = canvas_getcurrent(); + x->x_bytespersample = 2; + x->x_sfchannels = 1; + x->x_fd = -1; + x->x_buf = buf; + x->x_bufsize = bufsize; + x->x_fifosize = x->x_fifohead = x->x_fifotail = x->x_requestcode = 0; + pthread_create(&x->x_childthread, 0, readsf_child_main, x); + return (x); +} + +static void readsf_tick(t_readsf *x) +{ + outlet_bang(x->x_bangout); +} + +static t_int *readsf_perform(t_int *w) +{ + t_readsf *x = (t_readsf *)(w[1]); + int vecsize = x->x_vecsize, noutlets = x->x_noutlets, i, j, + bytespersample = x->x_bytespersample, + bigendian = x->x_bigendian; + t_sample *fp; + if (x->x_state == STATE_STREAM) + { + int wantbytes, nchannels, sfchannels = x->x_sfchannels; + pthread_mutex_lock(&x->x_mutex); + wantbytes = sfchannels * vecsize * bytespersample; + while ( + !x->x_eof && x->x_fifohead >= x->x_fifotail && + x->x_fifohead < x->x_fifotail + wantbytes-1) + { +#ifdef DEBUG_SOUNDFILE + pute("wait...\n"); +#endif + sfread_cond_signal(&x->x_requestcondition); + sfread_cond_wait(&x->x_answercondition, &x->x_mutex); + /* resync local cariables -- bug fix thanks to Shahrokh */ + vecsize = x->x_vecsize; + bytespersample = x->x_bytespersample; + sfchannels = x->x_sfchannels; + wantbytes = sfchannels * vecsize * bytespersample; + bigendian = x->x_bigendian; +#ifdef DEBUG_SOUNDFILE + pute("done\n"); +#endif + } + if (x->x_eof && x->x_fifohead >= x->x_fifotail && + x->x_fifohead < x->x_fifotail + wantbytes-1) + { + int xfersize; + if (x->x_fileerror) + { + pd_error(x, "dsp: %s: %s", x->x_filename, + (x->x_fileerror == EIO ? + "unknown or bad header format" : + strerror(x->x_fileerror))); + } + clock_delay(x->x_clock, 0); + x->x_state = STATE_IDLE; + + /* if there's a partial buffer left, copy it out. */ + xfersize = (x->x_fifohead - x->x_fifotail + 1) / + (sfchannels * bytespersample); + if (xfersize) + { + soundfile_xferin_sample(sfchannels, noutlets, x->x_outvec, 0, + (unsigned char *)(x->x_buf + x->x_fifotail), xfersize, + bytespersample, bigendian); + vecsize -= xfersize; + } + /* then zero out the (rest of the) output */ + for (i = 0; i < noutlets; i++) + for (j = vecsize, fp = x->x_outvec[i] + xfersize; j--; ) + *fp++ = 0; + + sfread_cond_signal(&x->x_requestcondition); + pthread_mutex_unlock(&x->x_mutex); + return (w+2); + } + + soundfile_xferin_sample(sfchannels, noutlets, x->x_outvec, 0, + (unsigned char *)(x->x_buf + x->x_fifotail), vecsize, + bytespersample, bigendian); + + x->x_fifotail += wantbytes; + if (x->x_fifotail >= x->x_fifosize) + x->x_fifotail = 0; + if ((--x->x_sigcountdown) <= 0) + { + sfread_cond_signal(&x->x_requestcondition); + x->x_sigcountdown = x->x_sigperiod; + } + pthread_mutex_unlock(&x->x_mutex); + } + else + { + for (i = 0; i < noutlets; i++) + for (j = vecsize, fp = x->x_outvec[i]; j--; ) + *fp++ = 0; + } + return (w+2); +} + +static void readsf_start(t_readsf *x) +{ + /* start making output. If we're in the "startup" state change + to the "running" state. */ + if (x->x_state == STATE_STARTUP) + x->x_state = STATE_STREAM; + else pd_error(x, "readsf: start requested with no prior 'open'"); +} + +static void readsf_stop(t_readsf *x) +{ + /* LATER rethink whether you need the mutex just to set a variable? */ + pthread_mutex_lock(&x->x_mutex); + x->x_state = STATE_IDLE; + x->x_requestcode = REQUEST_CLOSE; + sfread_cond_signal(&x->x_requestcondition); + pthread_mutex_unlock(&x->x_mutex); +} + +static void readsf_float(t_readsf *x, t_floatarg f) +{ + if (f != 0) + readsf_start(x); + else readsf_stop(x); +} + + /* open method. Called as: + open filename [skipframes headersize channels bytespersamp endianness] + (if headersize is zero, header is taken to be automatically + detected; thus, use the special "-1" to mean a truly headerless file.) + */ + +static void readsf_open(t_readsf *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *filesym = atom_getsymbolarg(0, argc, argv); + t_float onsetframes = atom_getfloatarg(1, argc, argv); + t_float headerbytes = atom_getfloatarg(2, argc, argv); + t_float channels = atom_getfloatarg(3, argc, argv); + t_float bytespersamp = atom_getfloatarg(4, argc, argv); + t_symbol *endian = atom_getsymbolarg(5, argc, argv); + if (!*filesym->s_name) + return; + pthread_mutex_lock(&x->x_mutex); + x->x_requestcode = REQUEST_OPEN; + x->x_filename = filesym->s_name; + x->x_fifotail = 0; + x->x_fifohead = 0; + if (*endian->s_name == 'b') + x->x_bigendian = 1; + else if (*endian->s_name == 'l') + x->x_bigendian = 0; + else if (*endian->s_name) + pd_error(x, "endianness neither 'b' nor 'l'"); + else x->x_bigendian = garray_ambigendian(); + x->x_onsetframes = (onsetframes > 0 ? onsetframes : 0); + x->x_skipheaderbytes = (headerbytes > 0 ? headerbytes : + (headerbytes == 0 ? -1 : 0)); + x->x_sfchannels = (channels >= 1 ? channels : 1); + x->x_bytespersample = (bytespersamp > 2 ? bytespersamp : 2); + x->x_eof = 0; + x->x_fileerror = 0; + x->x_state = STATE_STARTUP; + sfread_cond_signal(&x->x_requestcondition); + pthread_mutex_unlock(&x->x_mutex); +} + +static void readsf_dsp(t_readsf *x, t_signal **sp) +{ + int i, noutlets = x->x_noutlets; + pthread_mutex_lock(&x->x_mutex); + x->x_vecsize = sp[0]->s_n; + + x->x_sigperiod = (x->x_fifosize / + (x->x_bytespersample * x->x_sfchannels * x->x_vecsize)); + for (i = 0; i < noutlets; i++) + x->x_outvec[i] = sp[i]->s_vec; + pthread_mutex_unlock(&x->x_mutex); + dsp_add(readsf_perform, 1, x); +} + +static void readsf_print(t_readsf *x) +{ + post("state %d", x->x_state); + post("fifo head %d", x->x_fifohead); + post("fifo tail %d", x->x_fifotail); + post("fifo size %d", x->x_fifosize); + post("fd %d", x->x_fd); + post("eof %d", x->x_eof); +} + +static void readsf_free(t_readsf *x) +{ + /* request QUIT and wait for acknowledge */ + void *threadrtn; + pthread_mutex_lock(&x->x_mutex); + x->x_requestcode = REQUEST_QUIT; + sfread_cond_signal(&x->x_requestcondition); + while (x->x_requestcode != REQUEST_NOTHING) + { + sfread_cond_signal(&x->x_requestcondition); + sfread_cond_wait(&x->x_answercondition, &x->x_mutex); + } + pthread_mutex_unlock(&x->x_mutex); + if (pthread_join(x->x_childthread, &threadrtn)) + error("readsf_free: join failed"); + + pthread_cond_destroy(&x->x_requestcondition); + pthread_cond_destroy(&x->x_answercondition); + pthread_mutex_destroy(&x->x_mutex); + freebytes(x->x_buf, x->x_bufsize); + clock_free(x->x_clock); +} + +static void readsf_setup(void) +{ + readsf_class = class_new(gensym("readsf~"), (t_newmethod)readsf_new, + (t_method)readsf_free, sizeof(t_readsf), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addfloat(readsf_class, (t_method)readsf_float); + class_addmethod(readsf_class, (t_method)readsf_start, gensym("start"), 0); + class_addmethod(readsf_class, (t_method)readsf_stop, gensym("stop"), 0); + class_addmethod(readsf_class, (t_method)readsf_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(readsf_class, (t_method)readsf_open, gensym("open"), + A_GIMME, 0); + class_addmethod(readsf_class, (t_method)readsf_print, gensym("print"), 0); +} + +/******************************* writesf *******************/ + +static t_class *writesf_class; + +#define t_writesf t_readsf /* just re-use the structure */ + +/************** the child thread which performs file I/O ***********/ + +static void *writesf_child_main(void *zz) +{ + t_writesf *x = zz; +#ifdef DEBUG_SOUNDFILE + pute("1\n"); +#endif + pthread_mutex_lock(&x->x_mutex); + while (1) + { +#ifdef DEBUG_SOUNDFILE + pute("0\n"); +#endif + if (x->x_requestcode == REQUEST_NOTHING) + { +#ifdef DEBUG_SOUNDFILE + pute("wait 2\n"); +#endif + sfread_cond_signal(&x->x_answercondition); + sfread_cond_wait(&x->x_requestcondition, &x->x_mutex); +#ifdef DEBUG_SOUNDFILE + pute("3\n"); +#endif + } + else if (x->x_requestcode == REQUEST_OPEN) + { + char boo[80]; + int fd, writebytes; + long sysrtn; + + /* copy file stuff out of the data structure so we can + relinquish the mutex while we're in open_soundfile(). */ + long onsetframes = x->x_onsetframes; + long bytelimit = 0x7fffffff; + int skipheaderbytes = x->x_skipheaderbytes; + int bytespersample = x->x_bytespersample; + int sfchannels = x->x_sfchannels; + int bigendian = x->x_bigendian; + int filetype = x->x_filetype; + char *filename = x->x_filename; + t_canvas *canvas = x->x_canvas; + t_float samplerate = x->x_samplerate; + + /* alter the request code so that an ensuing "open" will get + noticed. */ +#ifdef DEBUG_SOUNDFILE + pute("4\n"); +#endif + x->x_requestcode = REQUEST_BUSY; + x->x_fileerror = 0; + + /* if there's already a file open, close it. This + should never happen since writesf_open() calls stop if + needed and then waits until we're idle. */ + if (x->x_fd >= 0) + { + int bytesperframe = x->x_bytespersample * x->x_sfchannels; + int bigendian = x->x_bigendian; + char *filename = x->x_filename; + int fd = x->x_fd; + int filetype = x->x_filetype; + int itemswritten = x->x_itemswritten; + int swap = x->x_swap; + pthread_mutex_unlock(&x->x_mutex); + + soundfile_finishwrite(x, filename, fd, + filetype, 0x7fffffff, itemswritten, + bytesperframe, swap); + close (fd); + + pthread_mutex_lock(&x->x_mutex); + x->x_fd = -1; +#ifdef DEBUG_SOUNDFILE + { + char s[1000]; + sprintf(s, "bug??? ditched %d\n", itemswritten); + pute(s); + } +#endif + if (x->x_requestcode != REQUEST_BUSY) + continue; + } + /* open the soundfile with the mutex unlocked */ + pthread_mutex_unlock(&x->x_mutex); + fd = create_soundfile(canvas, filename, filetype, 0, + bytespersample, bigendian, sfchannels, + garray_ambigendian() != bigendian, samplerate, 0); + pthread_mutex_lock(&x->x_mutex); +#ifdef DEBUG_SOUNDFILE + pute("5\n"); +#endif + + if (fd < 0) + { + x->x_fd = -1; + x->x_eof = 1; + x->x_fileerror = errno; +#ifdef DEBUG_SOUNDFILE + pute("open failed\n"); + pute(filename); +#endif + x->x_requestcode = REQUEST_NOTHING; + continue; + } + /* check if another request has been made; if so, field it */ + if (x->x_requestcode != REQUEST_BUSY) + continue; +#ifdef DEBUG_SOUNDFILE + pute("6\n"); +#endif + x->x_fd = fd; + x->x_fifotail = 0; + x->x_itemswritten = 0; + x->x_swap = garray_ambigendian() != bigendian; + /* in a loop, wait for the fifo to have data and write it + to disk */ + while (x->x_requestcode == REQUEST_BUSY || + (x->x_requestcode == REQUEST_CLOSE && + x->x_fifohead != x->x_fifotail)) + { + int fifosize = x->x_fifosize, fifotail; + char *buf = x->x_buf; +#ifdef DEBUG_SOUNDFILE + pute("77\n"); +#endif + /* if the head is < the tail, we can immediately write + from tail to end of fifo to disk; otherwise we hold off + writing until there are at least WRITESIZE bytes in the + buffer */ + if (x->x_fifohead < x->x_fifotail || + x->x_fifohead >= x->x_fifotail + WRITESIZE + || (x->x_requestcode == REQUEST_CLOSE && + x->x_fifohead != x->x_fifotail)) + { + writebytes = (x->x_fifohead < x->x_fifotail ? + fifosize : x->x_fifohead) - x->x_fifotail; + if (writebytes > READSIZE) + writebytes = READSIZE; + } + else + { +#ifdef DEBUG_SOUNDFILE + pute("wait 7a ...\n"); +#endif + sfread_cond_signal(&x->x_answercondition); +#ifdef DEBUG_SOUNDFILE + pute("signalled\n"); +#endif + sfread_cond_wait(&x->x_requestcondition, + &x->x_mutex); +#ifdef DEBUG_SOUNDFILE + pute("7a done\n"); +#endif + continue; + } +#ifdef DEBUG_SOUNDFILE + pute("8\n"); +#endif + fifotail = x->x_fifotail; + fd = x->x_fd; + pthread_mutex_unlock(&x->x_mutex); + sysrtn = write(fd, buf + fifotail, writebytes); + pthread_mutex_lock(&x->x_mutex); + if (x->x_requestcode != REQUEST_BUSY && + x->x_requestcode != REQUEST_CLOSE) + break; + if (sysrtn < writebytes) + { +#ifdef DEBUG_SOUNDFILE + pute("fileerror\n"); +#endif + x->x_fileerror = errno; + break; + } + else + { + x->x_fifotail += sysrtn; + if (x->x_fifotail == fifosize) + x->x_fifotail = 0; + } + x->x_itemswritten += + sysrtn / (x->x_bytespersample * x->x_sfchannels); +#ifdef DEBUG_SOUNDFILE + sprintf(boo, "after: head %d, tail %d written %d\n", + x->x_fifohead, x->x_fifotail, x->x_itemswritten); + pute(boo); +#endif + /* signal parent in case it's waiting for data */ + sfread_cond_signal(&x->x_answercondition); + } + } + else if (x->x_requestcode == REQUEST_CLOSE || + x->x_requestcode == REQUEST_QUIT) + { + int quit = (x->x_requestcode == REQUEST_QUIT); + if (x->x_fd >= 0) + { + int bytesperframe = x->x_bytespersample * x->x_sfchannels; + int bigendian = x->x_bigendian; + char *filename = x->x_filename; + int fd = x->x_fd; + int filetype = x->x_filetype; + int itemswritten = x->x_itemswritten; + int swap = x->x_swap; + pthread_mutex_unlock(&x->x_mutex); + + soundfile_finishwrite(x, filename, fd, + filetype, 0x7fffffff, itemswritten, + bytesperframe, swap); + close (fd); + + pthread_mutex_lock(&x->x_mutex); + x->x_fd = -1; + } + x->x_requestcode = REQUEST_NOTHING; + sfread_cond_signal(&x->x_answercondition); + if (quit) + break; + } + else + { +#ifdef DEBUG_SOUNDFILE + pute("13\n"); +#endif + } + } +#ifdef DEBUG_SOUNDFILE + pute("thread exit\n"); +#endif + pthread_mutex_unlock(&x->x_mutex); + return (0); +} + +/******** the object proper runs in the calling (parent) thread ****/ + +static void writesf_tick(t_writesf *x); + +static void *writesf_new(t_floatarg fnchannels, t_floatarg fbufsize) +{ + t_writesf *x; + int nchannels = fnchannels, bufsize = fbufsize, i; + char *buf; + + if (nchannels < 1) + nchannels = 1; + else if (nchannels > MAXSFCHANS) + nchannels = MAXSFCHANS; + if (bufsize <= 0) bufsize = DEFBUFPERCHAN * nchannels; + else if (bufsize < MINBUFSIZE) + bufsize = MINBUFSIZE; + else if (bufsize > MAXBUFSIZE) + bufsize = MAXBUFSIZE; + buf = getbytes(bufsize); + if (!buf) return (0); + + x = (t_writesf *)pd_new(writesf_class); + + for (i = 1; i < nchannels; i++) + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + + x->x_f = 0; + x->x_sfchannels = nchannels; + pthread_mutex_init(&x->x_mutex, 0); + pthread_cond_init(&x->x_requestcondition, 0); + pthread_cond_init(&x->x_answercondition, 0); + x->x_vecsize = MAXVECSIZE; + x->x_insamplerate = x->x_samplerate = 0; + x->x_state = STATE_IDLE; + x->x_clock = 0; /* no callback needed here */ + x->x_canvas = canvas_getcurrent(); + x->x_bytespersample = 2; + x->x_fd = -1; + x->x_buf = buf; + x->x_bufsize = bufsize; + x->x_fifosize = x->x_fifohead = x->x_fifotail = x->x_requestcode = 0; + pthread_create(&x->x_childthread, 0, writesf_child_main, x); + return (x); +} + +static t_int *writesf_perform(t_int *w) +{ + t_writesf *x = (t_writesf *)(w[1]); + int vecsize = x->x_vecsize, sfchannels = x->x_sfchannels, i, j, + bytespersample = x->x_bytespersample, + bigendian = x->x_bigendian; + t_sample *fp; + if (x->x_state == STATE_STREAM) + { + int wantbytes, roominfifo; + pthread_mutex_lock(&x->x_mutex); + wantbytes = sfchannels * vecsize * bytespersample; + roominfifo = x->x_fifotail - x->x_fifohead; + if (roominfifo <= 0) + roominfifo += x->x_fifosize; + while (roominfifo < wantbytes + 1) + { + fprintf(stderr, "writesf waiting for disk write..\n"); + fprintf(stderr, "(head %d, tail %d, room %d, want %d)\n", + x->x_fifohead, x->x_fifotail, roominfifo, wantbytes); + sfread_cond_signal(&x->x_requestcondition); + sfread_cond_wait(&x->x_answercondition, &x->x_mutex); + fprintf(stderr, "... done waiting.\n"); + roominfifo = x->x_fifotail - x->x_fifohead; + if (roominfifo <= 0) + roominfifo += x->x_fifosize; + } + + soundfile_xferout_sample(sfchannels, x->x_outvec, + (unsigned char *)(x->x_buf + x->x_fifohead), vecsize, 0, + bytespersample, bigendian, 1.); + + x->x_fifohead += wantbytes; + if (x->x_fifohead >= x->x_fifosize) + x->x_fifohead = 0; + if ((--x->x_sigcountdown) <= 0) + { +#ifdef DEBUG_SOUNDFILE + pute("signal 1\n"); +#endif + sfread_cond_signal(&x->x_requestcondition); + x->x_sigcountdown = x->x_sigperiod; + } + pthread_mutex_unlock(&x->x_mutex); + } + return (w+2); +} + +static void writesf_start(t_writesf *x) +{ + /* start making output. If we're in the "startup" state change + to the "running" state. */ + if (x->x_state == STATE_STARTUP) + x->x_state = STATE_STREAM; + else + pd_error(x, "writesf: start requested with no prior 'open'"); +} + +static void writesf_stop(t_writesf *x) +{ + /* LATER rethink whether you need the mutex just to set a Svariable? */ + pthread_mutex_lock(&x->x_mutex); + x->x_state = STATE_IDLE; + x->x_requestcode = REQUEST_CLOSE; +#ifdef DEBUG_SOUNDFILE + pute("signal 2\n"); +#endif + sfread_cond_signal(&x->x_requestcondition); + pthread_mutex_unlock(&x->x_mutex); +} + + + /* open method. Called as: open [args] filename with args as in + soundfiler_writeargparse(). + */ + +static void writesf_open(t_writesf *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *filesym; + int filetype, bytespersamp, swap, bigendian, normalize; + long onset, nframes; + t_float samplerate; + if (x->x_state != STATE_IDLE) + { + writesf_stop(x); + } + if (soundfiler_writeargparse(x, &argc, + &argv, &filesym, &filetype, &bytespersamp, &swap, &bigendian, + &normalize, &onset, &nframes, &samplerate)) + { + pd_error(x, + "writesf~: usage: open [-bytes [234]] [-wave,-nextstep,-aiff] ..."); + post("... [-big,-little] [-rate ####] filename"); + return; + } + if (normalize || onset || (nframes != 0x7fffffff)) + pd_error(x, "normalize/onset/nframes argument to writesf~: ignored"); + if (argc) + pd_error(x, "extra argument(s) to writesf~: ignored"); + pthread_mutex_lock(&x->x_mutex); + while (x->x_requestcode != REQUEST_NOTHING) + { + sfread_cond_signal(&x->x_requestcondition); + sfread_cond_wait(&x->x_answercondition, &x->x_mutex); + } + x->x_bytespersample = bytespersamp; + x->x_swap = swap; + x->x_bigendian = bigendian; + x->x_filename = filesym->s_name; + x->x_filetype = filetype; + x->x_itemswritten = 0; + x->x_requestcode = REQUEST_OPEN; + x->x_fifotail = 0; + x->x_fifohead = 0; + x->x_eof = 0; + x->x_fileerror = 0; + x->x_state = STATE_STARTUP; + x->x_bytespersample = (bytespersamp > 2 ? bytespersamp : 2); + if (samplerate > 0) + x->x_samplerate = samplerate; + else if (x->x_insamplerate > 0) + x->x_samplerate = x->x_insamplerate; + else x->x_samplerate = sys_getsr(); + /* set fifosize from bufsize. fifosize must be a + multiple of the number of bytes eaten for each DSP + tick. */ + x->x_fifosize = x->x_bufsize - (x->x_bufsize % + (x->x_bytespersample * x->x_sfchannels * MAXVECSIZE)); + /* arrange for the "request" condition to be signalled 16 + times per buffer */ + x->x_sigcountdown = x->x_sigperiod = (x->x_fifosize / + (16 * x->x_bytespersample * x->x_sfchannels * x->x_vecsize)); + sfread_cond_signal(&x->x_requestcondition); + pthread_mutex_unlock(&x->x_mutex); +} + +static void writesf_dsp(t_writesf *x, t_signal **sp) +{ + int i, ninlets = x->x_sfchannels; + pthread_mutex_lock(&x->x_mutex); + x->x_vecsize = sp[0]->s_n; + x->x_sigperiod = (x->x_fifosize / + (16 * x->x_bytespersample * x->x_sfchannels * x->x_vecsize)); + for (i = 0; i < ninlets; i++) + x->x_outvec[i] = sp[i]->s_vec; + x->x_insamplerate = sp[0]->s_sr; + pthread_mutex_unlock(&x->x_mutex); + dsp_add(writesf_perform, 1, x); +} + +static void writesf_print(t_writesf *x) +{ + post("state %d", x->x_state); + post("fifo head %d", x->x_fifohead); + post("fifo tail %d", x->x_fifotail); + post("fifo size %d", x->x_fifosize); + post("fd %d", x->x_fd); + post("eof %d", x->x_eof); +} + +static void writesf_free(t_writesf *x) +{ + /* request QUIT and wait for acknowledge */ + void *threadrtn; + pthread_mutex_lock(&x->x_mutex); + x->x_requestcode = REQUEST_QUIT; + /* post("stopping writesf thread..."); */ + sfread_cond_signal(&x->x_requestcondition); + while (x->x_requestcode != REQUEST_NOTHING) + { + /* post("signalling..."); */ + sfread_cond_signal(&x->x_requestcondition); + sfread_cond_wait(&x->x_answercondition, &x->x_mutex); + } + pthread_mutex_unlock(&x->x_mutex); + if (pthread_join(x->x_childthread, &threadrtn)) + error("writesf_free: join failed"); + /* post("... done."); */ + + pthread_cond_destroy(&x->x_requestcondition); + pthread_cond_destroy(&x->x_answercondition); + pthread_mutex_destroy(&x->x_mutex); + freebytes(x->x_buf, x->x_bufsize); +} + +static void writesf_setup(void) +{ + writesf_class = class_new(gensym("writesf~"), (t_newmethod)writesf_new, + (t_method)writesf_free, sizeof(t_writesf), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(writesf_class, (t_method)writesf_start, gensym("start"), 0); + class_addmethod(writesf_class, (t_method)writesf_stop, gensym("stop"), 0); + class_addmethod(writesf_class, (t_method)writesf_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(writesf_class, (t_method)writesf_open, gensym("open"), + A_GIMME, 0); + class_addmethod(writesf_class, (t_method)writesf_print, gensym("print"), 0); + CLASS_MAINSIGNALIN(writesf_class, t_writesf, x_f); +} + +/* ------------------------ global setup routine ------------------------- */ + +void d_soundfile_setup(void) +{ + soundfiler_setup(); + readsf_setup(); + writesf_setup(); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/d_ugen.c b/ports/camomile/source/LibPd/pure-data/src/d_ugen.c new file mode 100644 index 00000000..145d1753 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/d_ugen.c @@ -0,0 +1,1240 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* These routines build a copy of the DSP portion of a graph, which is + then sorted into a linear list of DSP operations which are added to + the DSP duty cycle called by the scheduler. Once that's been done, + we delete the copy. The DSP objects are represented by "ugenbox" + structures which are parallel to the DSP objects in the graph and + have vectors of siginlets and sigoutlets which record their + interconnections. +*/ + +#include "m_pd.h" +#include "m_imp.h" +#include +#include + +extern t_class *vinlet_class, *voutlet_class, *canvas_class, *text_class; +t_float *obj_findsignalscalar(t_object *x, int m); + +EXTERN_STRUCT _vinlet; +EXTERN_STRUCT _voutlet; + +void vinlet_dspprolog(struct _vinlet *x, t_signal **parentsigs, + int myvecsize, int calcsize, int phase, int period, int frequency, + int downsample, int upsample, int reblock, int switched); +void voutlet_dspprolog(struct _voutlet *x, t_signal **parentsigs, + int myvecsize, int calcsize, int phase, int period, int frequency, + int downsample, int upsample, int reblock, int switched); +void voutlet_dspepilog(struct _voutlet *x, t_signal **parentsigs, + int myvecsize, int calcsize, int phase, int period, int frequency, + int downsample, int upsample, int reblock, int switched); + +struct _instanceugen +{ + t_int *u_dspchain; /* DSP chain */ + int u_dspchainsize; /* number of elements in DSP chain */ + t_signal *u_signals; /* list of signals used by DSP chain */ + int u_sortno; /* number of DSP sortings so far */ + /* list of signals which can be reused, sorted by buffer size */ + t_signal *u_freelist[MAXLOGSIG+1]; + /* list of reusable "borrowed" signals (which don't own sample buffers) */ + t_signal *u_freeborrowed; + int u_phase; + int u_loud; + struct _dspcontext *u_context; +}; + +#define THIS (pd_this->pd_ugen) + +void d_ugen_newpdinstance( void) +{ + THIS = getbytes(sizeof(*THIS)); + THIS->u_dspchain = 0; + THIS->u_dspchainsize = 0; + THIS->u_signals = 0; +} + +void d_ugen_freepdinstance( void) +{ + freebytes(THIS, sizeof(*THIS)); +} + +t_int *zero_perform(t_int *w) /* zero out a vector */ +{ + t_sample *out = (t_sample *)(w[1]); + int n = (int)(w[2]); + while (n--) *out++ = 0; + return (w+3); +} + +t_int *zero_perf8(t_int *w) +{ + t_sample *out = (t_sample *)(w[1]); + int n = (int)(w[2]); + + for (; n; n -= 8, out += 8) + { + out[0] = 0; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = 0; + out[6] = 0; + out[7] = 0; + } + return (w+3); +} + +void dsp_add_zero(t_sample *out, int n) +{ + if (n&7) + dsp_add(zero_perform, 2, out, n); + else + dsp_add(zero_perf8, 2, out, n); +} + +/* ---------------------------- block~ ----------------------------- */ + +/* The "block~ object maintains the containing canvas's DSP computation, +calling it at a super- or sub-multiple of the containing canvas's +calling frequency. The block~'s creation arguments specify block size +and overlap. Block~ does no "dsp" computation in its own right, but it +adds prolog and epilog code before and after the canvas's unit generators. + +A subcanvas need not have a block~ at all; if there's none, its +ugens are simply put on the list without any prolog or epilog code. + +Block~ may be invoked as switch~, in which case it also acts to switch the +subcanvas on and off. The overall order of scheduling for a subcanvas +is thus, + + inlet and outlet prologue code (1) + block prologue (2) + the objects in the subcanvas, including inlets and outlets + block epilogue (2) + outlet epilogue code (2) + +where (1) means, "if reblocked" and (2) means, "if reblocked or switched". + +If we're reblocked, the inlet prolog and outlet epilog code takes care of +overlapping and buffering to deal with vector size changes. If we're switched +but not reblocked, the inlet prolog is not needed, and the output epilog is +ONLY run when the block is switched off; in this case the epilog code simply +copies zeros to all signal outlets. +*/ + +static t_class *block_class; + +typedef struct _block +{ + t_object x_obj; + int x_vecsize; /* size of audio signals in this block */ + int x_calcsize; /* number of samples actually to compute */ + int x_overlap; + int x_phase; /* from 0 to period-1; when zero we run the block */ + int x_period; /* submultiple of containing canvas */ + int x_frequency; /* supermultiple of comtaining canvas */ + int x_count; /* number of times parent block has called us */ + int x_chainonset; /* beginning of code in DSP chain */ + int x_blocklength; /* length of dspchain for this block */ + int x_epiloglength; /* length of epilog */ + char x_switched; /* true if we're acting as a a switch */ + char x_switchon; /* true if we're switched on */ + char x_reblock; /* true if inlets and outlets are reblocking */ + int x_upsample; /* upsampling-factor */ + int x_downsample; /* downsampling-factor */ + int x_return; /* stop right after this block (for one-shots) */ +} t_block; + +static void block_set(t_block *x, t_floatarg fvecsize, t_floatarg foverlap, + t_floatarg fupsample); + +static void *block_new(t_floatarg fvecsize, t_floatarg foverlap, + t_floatarg fupsample) +{ + t_block *x = (t_block *)pd_new(block_class); + x->x_phase = 0; + x->x_period = 1; + x->x_frequency = 1; + x->x_switched = 0; + x->x_switchon = 1; + block_set(x, fvecsize, foverlap, fupsample); + return (x); +} + +static void block_set(t_block *x, t_floatarg fcalcsize, t_floatarg foverlap, + t_floatarg fupsample) +{ + int upsample, downsample; + int calcsize = fcalcsize; + int overlap = foverlap; + int dspstate = canvas_suspend_dsp(); + int vecsize; + if (overlap < 1) + overlap = 1; + if (calcsize < 0) + calcsize = 0; /* this means we'll get it from parent later. */ + + if (fupsample <= 0) + upsample = downsample = 1; + else if (fupsample >= 1) { + upsample = fupsample; + downsample = 1; + } + else + { + downsample = 1.0 / fupsample; + upsample = 1; + } + + /* vecsize is smallest power of 2 large enough to hold calcsize */ + if (calcsize) + { + if ((vecsize = (1 << ilog2(calcsize))) != calcsize) + vecsize *= 2; + } + else vecsize = 0; + if (vecsize && (vecsize != (1 << ilog2(vecsize)))) + { + pd_error(x, "block~: vector size not a power of 2"); + vecsize = 64; + } + if (overlap != (1 << ilog2(overlap))) + { + pd_error(x, "block~: overlap not a power of 2"); + overlap = 1; + } + if (downsample != (1 << ilog2(downsample))) + { + pd_error(x, "block~: downsampling not a power of 2"); + downsample = 1; + } + if (upsample != (1 << ilog2(upsample))) + { + pd_error(x, "block~: upsampling not a power of 2"); + upsample = 1; + } + + x->x_calcsize = calcsize; + x->x_vecsize = vecsize; + x->x_overlap = overlap; + x->x_upsample = upsample; + x->x_downsample = downsample; + canvas_resume_dsp(dspstate); +} + +static void *switch_new(t_floatarg fvecsize, t_floatarg foverlap, + t_floatarg fupsample) +{ + t_block *x = (t_block *)(block_new(fvecsize, foverlap, fupsample)); + x->x_switched = 1; + x->x_switchon = 0; + return (x); +} + +static void block_float(t_block *x, t_floatarg f) +{ + if (x->x_switched) + x->x_switchon = (f != 0); +} + +static void block_bang(t_block *x) +{ + if (x->x_switched && !x->x_switchon && THIS->u_dspchain) + { + t_int *ip; + x->x_return = 1; + for (ip = THIS->u_dspchain + x->x_chainonset; ip; ) + ip = (*(t_perfroutine)(*ip))(ip); + x->x_return = 0; + } + else pd_error(x, "bang to block~ or on-state switch~ has no effect"); +} + + +#define PROLOGCALL 2 +#define EPILOGCALL 2 + +static t_int *block_prolog(t_int *w) +{ + t_block *x = (t_block *)w[1]; + int phase = x->x_phase; + /* if we're switched off, jump past the epilog code */ + if (!x->x_switchon) + return (w + x->x_blocklength); + if (phase) + { + phase++; + if (phase == x->x_period) phase = 0; + x->x_phase = phase; + return (w + x->x_blocklength); /* skip block; jump past epilog */ + } + else + { + x->x_count = x->x_frequency; + x->x_phase = (x->x_period > 1 ? 1 : 0); + return (w + PROLOGCALL); /* beginning of block is next ugen */ + } +} + +static t_int *block_epilog(t_int *w) +{ + t_block *x = (t_block *)w[1]; + int count = x->x_count - 1; + if (x->x_return) + return (0); + if (!x->x_reblock) + return (w + x->x_epiloglength + EPILOGCALL); + if (count) + { + x->x_count = count; + return (w - (x->x_blocklength - + (PROLOGCALL + EPILOGCALL))); /* go to ugen after prolog */ + } + else return (w + EPILOGCALL); +} + +static void block_dsp(t_block *x, t_signal **sp) +{ + /* do nothing here */ +} + +void block_tilde_setup(void) +{ + block_class = class_new(gensym("block~"), (t_newmethod)block_new, 0, + sizeof(t_block), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addcreator((t_newmethod)switch_new, gensym("switch~"), + A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(block_class, (t_method)block_set, gensym("set"), + A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(block_class, (t_method)block_dsp, gensym("dsp"), A_CANT, 0); + class_addfloat(block_class, block_float); + class_addbang(block_class, block_bang); +} + +/* ------------------ DSP call list ----------------------- */ + +static t_int dsp_done(t_int *w) +{ + return (0); +} + +void dsp_add(t_perfroutine f, int n, ...) +{ + int newsize = THIS->u_dspchainsize + n+1, i; + va_list ap; + + THIS->u_dspchain = t_resizebytes(THIS->u_dspchain, + THIS->u_dspchainsize * sizeof (t_int), newsize * sizeof (t_int)); + THIS->u_dspchain[THIS->u_dspchainsize-1] = (t_int)f; + if (THIS->u_loud) + post("add to chain: %lx", + THIS->u_dspchain[THIS->u_dspchainsize-1]); + va_start(ap, n); + for (i = 0; i < n; i++) + { + THIS->u_dspchain[THIS->u_dspchainsize + i] = va_arg(ap, t_int); + if (THIS->u_loud) + post("add to chain: %lx", + THIS->u_dspchain[THIS->u_dspchainsize + i]); + } + va_end(ap); + THIS->u_dspchain[newsize-1] = (t_int)dsp_done; + THIS->u_dspchainsize = newsize; +} + + /* at Guenter's suggestion, here's a vectorized version */ +void dsp_addv(t_perfroutine f, int n, t_int *vec) +{ + int newsize = THIS->u_dspchainsize + n+1, i; + + THIS->u_dspchain = t_resizebytes(THIS->u_dspchain, + THIS->u_dspchainsize * sizeof (t_int), newsize * sizeof (t_int)); + THIS->u_dspchain[THIS->u_dspchainsize-1] = (t_int)f; + for (i = 0; i < n; i++) + THIS->u_dspchain[THIS->u_dspchainsize + i] = vec[i]; + THIS->u_dspchain[newsize-1] = (t_int)dsp_done; + THIS->u_dspchainsize = newsize; +} + +void dsp_tick(void) +{ + if (THIS->u_dspchain) + { + t_int *ip; + for (ip = THIS->u_dspchain; ip; ) ip = (*(t_perfroutine)(*ip))(ip); + THIS->u_phase++; + } +} + +/* ---------------- signals ---------------------------- */ + +int ilog2(int n) +{ + int r = -1; + if (n <= 0) return(0); + while (n) + { + r++; + n >>= 1; + } + return (r); +} + + + /* call this when DSP is stopped to free all the signals */ +void signal_cleanup(void) +{ + t_signal **svec, *sig, *sig2; + int i; + while ((sig = THIS->u_signals)) + { + THIS->u_signals = sig->s_nextused; + if (!sig->s_isborrowed) + t_freebytes(sig->s_vec, sig->s_vecsize * sizeof (*sig->s_vec)); + t_freebytes(sig, sizeof *sig); + } + for (i = 0; i <= MAXLOGSIG; i++) + THIS->u_freelist[i] = 0; + THIS->u_freeborrowed = 0; +} + + /* mark the signal "reusable." */ +void signal_makereusable(t_signal *sig) +{ + int logn = ilog2(sig->s_vecsize); +#if 1 + t_signal *s5; + for (s5 = THIS->u_freeborrowed; s5; s5 = s5->s_nextfree) + { + if (s5 == sig) + { + bug("signal_free 3"); + return; + } + } + for (s5 = THIS->u_freelist[logn]; s5; s5 = s5->s_nextfree) + { + if (s5 == sig) + { + bug("signal_free 4"); + return; + } + } +#endif + if (THIS->u_loud) post("free %lx: %d", sig, sig->s_isborrowed); + if (sig->s_isborrowed) + { + /* if the signal is borrowed, decrement the borrowed-from signal's + reference count, possibly marking it reusable too */ + t_signal *s2 = sig->s_borrowedfrom; + if ((s2 == sig) || !s2) + bug("signal_free"); + s2->s_refcount--; + if (!s2->s_refcount) + signal_makereusable(s2); + sig->s_nextfree = THIS->u_freeborrowed; + THIS->u_freeborrowed = sig; + } + else + { + /* if it's a real signal (not borrowed), put it on the free list + so we can reuse it. */ + if (THIS->u_freelist[logn] == sig) bug("signal_free 2"); + sig->s_nextfree = THIS->u_freelist[logn]; + THIS->u_freelist[logn] = sig; + } +} + + /* reclaim or make an audio signal. If n is zero, return a "borrowed" + signal whose buffer and size will be obtained later via + signal_setborrowed(). */ + +t_signal *signal_new(int n, t_float sr) +{ + int logn, n2, vecsize = 0; + t_signal *ret, **whichlist; + t_sample *fp; + logn = ilog2(n); + if (n) + { + if ((vecsize = (1< MAXLOGSIG) + bug("signal buffer too large"); + whichlist = THIS->u_freelist + logn; + } + else + whichlist = &THIS->u_freeborrowed; + + /* first try to reclaim one from the free list */ + if ((ret = *whichlist)) + *whichlist = ret->s_nextfree; + else + { + /* LATER figure out what to do for out-of-space here! */ + ret = (t_signal *)t_getbytes(sizeof *ret); + if (n) + { + ret->s_vec = (t_sample *)getbytes(vecsize * sizeof (*ret->s_vec)); + ret->s_isborrowed = 0; + } + else + { + ret->s_vec = 0; + ret->s_isborrowed = 1; + } + ret->s_nextused = THIS->u_signals; + THIS->u_signals = ret; + } + ret->s_n = n; + ret->s_vecsize = vecsize; + ret->s_sr = sr; + ret->s_refcount = 0; + ret->s_borrowedfrom = 0; + if (THIS->u_loud) post("new %lx: %lx", ret, ret->s_vec); + return (ret); +} + +static t_signal *signal_newlike(const t_signal *sig) +{ + return (signal_new(sig->s_n, sig->s_sr)); +} + +void signal_setborrowed(t_signal *sig, t_signal *sig2) +{ + if (!sig->s_isborrowed || sig->s_borrowedfrom) + bug("signal_setborrowed"); + if (sig == sig2) + bug("signal_setborrowed 2"); + sig->s_borrowedfrom = sig2; + sig->s_vec = sig2->s_vec; + sig->s_n = sig2->s_n; + sig->s_vecsize = sig2->s_vecsize; + if (THIS->u_loud) post("set borrowed %lx: %lx", sig, sig->s_vec); +} + +int signal_compatible(t_signal *s1, t_signal *s2) +{ + return (s1->s_n == s2->s_n && s1->s_sr == s2->s_sr); +} + +/* ------------------ ugen ("unit generator") sorting ----------------- */ + +typedef struct _ugenbox +{ + struct _siginlet *u_in; + int u_nin; + struct _sigoutlet *u_out; + int u_nout; + int u_phase; + struct _ugenbox *u_next; + t_object *u_obj; + int u_done; +} t_ugenbox; + +typedef struct _siginlet +{ + int i_nconnect; + int i_ngot; + t_signal *i_signal; +} t_siginlet; + +typedef struct _sigoutconnect +{ + t_ugenbox *oc_who; + int oc_inno; + struct _sigoutconnect *oc_next; +} t_sigoutconnect; + +typedef struct _sigoutlet +{ + int o_nconnect; + int o_nsent; + t_signal *o_signal; + t_sigoutconnect *o_connections; +} t_sigoutlet; + + +struct _dspcontext +{ + struct _ugenbox *dc_ugenlist; + struct _dspcontext *dc_parentcontext; + int dc_ninlets; + int dc_noutlets; + t_signal **dc_iosigs; + t_float dc_srate; + int dc_vecsize; /* vector size, power of two */ + int dc_calcsize; /* number of elements to calculate */ + char dc_toplevel; /* true if "iosigs" is invalid. */ + char dc_reblock; /* true if we have to reblock inlets/outlets */ + char dc_switched; /* true if we're switched */ +}; + +#define t_dspcontext struct _dspcontext + + /* get a new signal for the current context - used by clone~ object */ +t_signal *signal_newfromcontext(int borrowed) +{ + return (signal_new((borrowed? 0 : THIS->u_context->dc_calcsize), + THIS->u_context->dc_srate)); +} + +void ugen_stop(void) +{ + t_signal *s; + int i; + if (THIS->u_dspchain) + { + freebytes(THIS->u_dspchain, + THIS->u_dspchainsize * sizeof (t_int)); + THIS->u_dspchain = 0; + } + signal_cleanup(); + +} + +void ugen_start(void) +{ + ugen_stop(); + THIS->u_sortno++; + THIS->u_dspchain = (t_int *)getbytes(sizeof(*THIS->u_dspchain)); + THIS->u_dspchain[0] = (t_int)dsp_done; + THIS->u_dspchainsize = 1; + if (THIS->u_context) bug("ugen_start"); +} + +int ugen_getsortno(void) +{ + return (THIS->u_sortno); +} + +#if 1 +void glob_foo(void *dummy, t_symbol *s, int argc, t_atom *argv) +{ + int i, count; + t_signal *sig; + for (count = 0, sig = THIS->u_signals; sig; + count++, sig = sig->s_nextused) + ; + post("used signals %d", count); + for (i = 0; i < MAXLOGSIG; i++) + { + for (count = 0, sig = THIS->u_freelist[i]; sig; + count++, sig = sig->s_nextfree) + ; + if (count) + post("size %d: free %d", (1 << i), count); + } + for (count = 0, sig = THIS->u_freeborrowed; sig; + count++, sig = sig->s_nextfree) + ; + post("free borrowed %d", count); + + THIS->u_loud = argc; +} +#endif + + /* start building the graph for a canvas */ +t_dspcontext *ugen_start_graph(int toplevel, t_signal **sp, + int ninlets, int noutlets) +{ + t_dspcontext *dc = (t_dspcontext *)getbytes(sizeof(*dc)); + int parent_vecsize, vecsize; + + if (THIS->u_loud) post("ugen_start_graph..."); + + /* protect against invalid numsignals. This might happen if we have + an abstraction with inlet~/outlet~ opened as a toplevel patch */ + if (toplevel) + ninlets = noutlets = 0; + + dc->dc_ugenlist = 0; + dc->dc_toplevel = toplevel; + dc->dc_iosigs = sp; + dc->dc_ninlets = ninlets; + dc->dc_noutlets = noutlets; + dc->dc_parentcontext = THIS->u_context; + THIS->u_context = dc; + return (dc); +} + + /* first the canvas calls this to create all the boxes... */ +void ugen_add(t_dspcontext *dc, t_object *obj) +{ + t_ugenbox *x = (t_ugenbox *)getbytes(sizeof *x); + int i; + t_sigoutlet *uout; + t_siginlet *uin; + + x->u_next = dc->dc_ugenlist; + dc->dc_ugenlist = x; + x->u_obj = obj; + x->u_nin = obj_nsiginlets(obj); + x->u_in = getbytes(x->u_nin * sizeof (*x->u_in)); + for (uin = x->u_in, i = x->u_nin; i--; uin++) + uin->i_nconnect = 0; + x->u_nout = obj_nsigoutlets(obj); + x->u_out = getbytes(x->u_nout * sizeof (*x->u_out)); + for (uout = x->u_out, i = x->u_nout; i--; uout++) + uout->o_connections = 0, uout->o_nconnect = 0; +} + + /* and then this to make all the connections. */ +void ugen_connect(t_dspcontext *dc, t_object *x1, int outno, t_object *x2, + int inno) +{ + t_ugenbox *u1, *u2; + t_sigoutlet *uout; + t_siginlet *uin; + t_sigoutconnect *oc; + int sigoutno = obj_sigoutletindex(x1, outno); + int siginno = obj_siginletindex(x2, inno); + if (THIS->u_loud) + post("%s -> %s: %d->%d", + class_getname(x1->ob_pd), + class_getname(x2->ob_pd), outno, inno); + for (u1 = dc->dc_ugenlist; u1 && u1->u_obj != x1; u1 = u1->u_next); + for (u2 = dc->dc_ugenlist; u2 && u2->u_obj != x2; u2 = u2->u_next); + if (!u1 || !u2 || siginno < 0 || !u2->u_nin) + { + if (!u1) + error("object with signal outlets but no DSP method?"); + /* check if it's a "text" (i.e., object wasn't created) - + if so fail silently */ + else if (!(x2 && (pd_class(&x2->ob_pd) == text_class))) + pd_error(u1->u_obj, + "signal outlet connect to nonsignal inlet (ignored)"); + return; + } + if (sigoutno < 0 || sigoutno >= u1->u_nout || siginno >= u2->u_nin) + { + bug("ugen_connect %s %s %d %d (%d %d)", + class_getname(x1->ob_pd), + class_getname(x2->ob_pd), sigoutno, siginno, u1->u_nout, + u2->u_nin); + } + uout = u1->u_out + sigoutno; + uin = u2->u_in + siginno; + + /* add a new connection to the outlet's list */ + oc = (t_sigoutconnect *)getbytes(sizeof *oc); + oc->oc_next = uout->o_connections; + uout->o_connections = oc; + oc->oc_who = u2; + oc->oc_inno = siginno; + /* update inlet and outlet counts */ + uout->o_nconnect++; + uin->i_nconnect++; +} + + /* get the index of a ugenbox or -1 if it's not on the list */ +static int ugen_index(t_dspcontext *dc, t_ugenbox *x) +{ + int ret; + t_ugenbox *u; + for (u = dc->dc_ugenlist, ret = 0; u; u = u->u_next, ret++) + if (u == x) return (ret); + return (-1); +} +extern t_class *clone_class; + + /* put a ugenbox on the chain, recursively putting any others on that + this one might uncover. */ +static void ugen_doit(t_dspcontext *dc, t_ugenbox *u) +{ + t_sigoutlet *uout; + t_siginlet *uin; + t_sigoutconnect *oc, *oc2; + t_class *class = pd_class(&u->u_obj->ob_pd); + int i, n; + /* suppress creating new signals for the outputs of signal + inlets and subpatchs; except in the case we're an inlet and "blocking" + is set. We don't yet know if a subcanvas will be "blocking" so there + we delay new signal creation, which will be handled by calling + signal_setborrowed in the ugen_done_graph routine below. */ + int nonewsigs = (class == canvas_class || + ((class == vinlet_class) && !(dc->dc_reblock))); + /* when we encounter a subcanvas or a signal outlet, suppress freeing + the input signals as they may be "borrowed" for the super or sub + patch; same exception as above, but also if we're "switched" we + have to do a copy rather than a borrow. */ + int nofreesigs = (class == canvas_class || class == clone_class || + ((class == voutlet_class) && !(dc->dc_reblock || dc->dc_switched))); + t_signal **insig, **outsig, **sig, *s1, *s2, *s3; + t_ugenbox *u2; + + if (THIS->u_loud) post("doit %s %d %d", class_getname(class), nofreesigs, + nonewsigs); + for (i = 0, uin = u->u_in; i < u->u_nin; i++, uin++) + { + if (!uin->i_nconnect) + { + t_float *scalar; + s3 = signal_new(dc->dc_calcsize, dc->dc_srate); + /* post("%s: unconnected signal inlet set to zero", + class_getname(u->u_obj->ob_pd)); */ + if ((scalar = obj_findsignalscalar(u->u_obj, i))) + dsp_add_scalarcopy(scalar, s3->s_vec, s3->s_n); + else + dsp_add_zero(s3->s_vec, s3->s_n); + uin->i_signal = s3; + s3->s_refcount = 1; + } + } + insig = (t_signal **)getbytes((u->u_nin + u->u_nout) * sizeof(t_signal *)); + outsig = insig + u->u_nin; + for (sig = insig, uin = u->u_in, i = u->u_nin; i--; sig++, uin++) + { + int newrefcount; + *sig = uin->i_signal; + newrefcount = --(*sig)->s_refcount; + /* if the reference count went to zero, we free the signal now, + unless it's a subcanvas or outlet; these might keep the + signal around to send to objects connected to them. In this + case we increment the reference count; the corresponding decrement + is in sig_makereusable(). */ + if (nofreesigs) + (*sig)->s_refcount++; + else if (!newrefcount) + signal_makereusable(*sig); + } + for (sig = outsig, uout = u->u_out, i = u->u_nout; i--; sig++, uout++) + { + /* similarly, for outlets of subcanvases we delay creating + them; instead we create "borrowed" ones so that the refcount + is known. The subcanvas replaces the fake signal with one showing + where the output data actually is, to avoid having to copy it. + For any other object, we just allocate a new output vector; + since we've already freed the inputs the objects might get called + "in place." */ + if (nonewsigs) + { + *sig = uout->o_signal = + signal_new(0, dc->dc_srate); + } + else + *sig = uout->o_signal = signal_new(dc->dc_calcsize, dc->dc_srate); + (*sig)->s_refcount = uout->o_nconnect; + } + /* now call the DSP scheduling routine for the ugen. This + routine must fill in "borrowed" signal outputs in case it's either + a subcanvas or a signal inlet. */ + mess1(&u->u_obj->ob_pd, gensym("dsp"), insig); + + /* if any output signals aren't connected to anyone, free them + now; otherwise they'll either get freed when the reference count + goes back to zero, or even later as explained above. */ + + for (sig = outsig, uout = u->u_out, i = u->u_nout; i--; sig++, uout++) + { + if (!(*sig)->s_refcount) + signal_makereusable(*sig); + } + if (THIS->u_loud) + { + if (u->u_nin + u->u_nout == 0) post("put %s %d", + class_getname(u->u_obj->ob_pd), ugen_index(dc, u)); + else if (u->u_nin + u->u_nout == 1) post("put %s %d (%lx)", + class_getname(u->u_obj->ob_pd), ugen_index(dc, u), sig[0]); + else if (u->u_nin + u->u_nout == 2) post("put %s %d (%lx %lx)", + class_getname(u->u_obj->ob_pd), ugen_index(dc, u), + sig[0], sig[1]); + else post("put %s %d (%lx %lx %lx ...)", + class_getname(u->u_obj->ob_pd), ugen_index(dc, u), + sig[0], sig[1], sig[2]); + } + + /* pass it on and trip anyone whose last inlet was filled */ + for (uout = u->u_out, i = u->u_nout; i--; uout++) + { + s1 = uout->o_signal; + for (oc = uout->o_connections; oc; oc = oc->oc_next) + { + u2 = oc->oc_who; + uin = &u2->u_in[oc->oc_inno]; + /* if there's already someone here, sum the two */ + if ((s2 = uin->i_signal)) + { + s1->s_refcount--; + s2->s_refcount--; + if (!signal_compatible(s1, s2)) + { + pd_error(u->u_obj, "%s: incompatible signal inputs", + class_getname(u->u_obj->ob_pd)); + return; + } + s3 = signal_newlike(s1); + dsp_add_plus(s1->s_vec, s2->s_vec, s3->s_vec, s1->s_n); + uin->i_signal = s3; + s3->s_refcount = 1; + if (!s1->s_refcount) signal_makereusable(s1); + if (!s2->s_refcount) signal_makereusable(s2); + } + else uin->i_signal = s1; + uin->i_ngot++; + /* if we didn't fill this inlet don't bother yet */ + if (uin->i_ngot < uin->i_nconnect) + goto notyet; + /* if there's more than one, check them all */ + if (u2->u_nin > 1) + { + for (uin = u2->u_in, n = u2->u_nin; n--; uin++) + if (uin->i_ngot < uin->i_nconnect) goto notyet; + } + /* so now we can schedule the ugen. */ + ugen_doit(dc, u2); + notyet: ; + } + } + t_freebytes(insig,(u->u_nin + u->u_nout) * sizeof(t_signal *)); + u->u_done = 1; +} + + /* once the DSP graph is built, we call this routine to sort it. + This routine also deletes the graph; later we might want to leave the + graph around, in case the user is editing the DSP network, to save having + to recreate it all the time. But not today. */ + +void ugen_done_graph(t_dspcontext *dc) +{ + t_ugenbox *u, *u2; + t_sigoutlet *uout; + t_siginlet *uin; + t_sigoutconnect *oc, *oc2; + int i, n; + t_block *blk; + t_dspcontext *parent_context = dc->dc_parentcontext; + t_float parent_srate; + int parent_vecsize; + int period, frequency, phase, vecsize, calcsize; + t_float srate; + int chainblockbegin; /* DSP chain onset before block prolog code */ + int chainblockend; /* and after block epilog code */ + int chainafterall; /* and after signal outlet epilog */ + int reblock = 0, switched; + int downsample = 1, upsample = 1; + /* debugging printout */ + + if (THIS->u_loud) + { + post("ugen_done_graph..."); + for (u = dc->dc_ugenlist; u; u = u->u_next) + { + post("ugen: %s", class_getname(u->u_obj->ob_pd)); + for (uout = u->u_out, i = 0; i < u->u_nout; uout++, i++) + for (oc = uout->o_connections; oc; oc = oc->oc_next) + { + post("... out %d to %s, index %d, inlet %d", i, + class_getname(oc->oc_who->u_obj->ob_pd), + ugen_index(dc, oc->oc_who), oc->oc_inno); + } + } + } + + /* search for an object of class "block~" */ + for (u = dc->dc_ugenlist, blk = 0; u; u = u->u_next) + { + t_pd *zz = &u->u_obj->ob_pd; + if (pd_class(zz) == block_class) + { + if (blk) + pd_error(blk, "conflicting block~ objects in same page"); + else blk = (t_block *)zz; + } + } + + /* figure out block size, calling frequency, sample rate */ + if (parent_context) + { + parent_srate = parent_context->dc_srate; + parent_vecsize = parent_context->dc_vecsize; + } + else + { + parent_srate = sys_getsr(); + parent_vecsize = sys_getblksize(); + } + if (blk) + { + int realoverlap; + vecsize = blk->x_vecsize; + if (vecsize == 0) + vecsize = parent_vecsize; + calcsize = blk->x_calcsize; + if (calcsize == 0) + calcsize = vecsize; + realoverlap = blk->x_overlap; + if (realoverlap > vecsize) realoverlap = vecsize; + downsample = blk->x_downsample; + upsample = blk->x_upsample; + if (downsample > parent_vecsize) + downsample = parent_vecsize; + period = (vecsize * downsample)/ + (parent_vecsize * realoverlap * upsample); + frequency = (parent_vecsize * realoverlap * upsample)/ + (vecsize * downsample); + phase = blk->x_phase; + srate = parent_srate * realoverlap * upsample / downsample; + if (period < 1) period = 1; + if (frequency < 1) frequency = 1; + blk->x_frequency = frequency; + blk->x_period = period; + blk->x_phase = THIS->u_phase & (period - 1); + if (! parent_context || (realoverlap != 1) || + (vecsize != parent_vecsize) || + (downsample != 1) || (upsample != 1)) + reblock = 1; + switched = blk->x_switched; + } + else + { + srate = parent_srate; + vecsize = parent_vecsize; + calcsize = (parent_context ? parent_context->dc_calcsize : vecsize); + downsample = upsample = 1; + period = frequency = 1; + phase = 0; + if (!parent_context) reblock = 1; + switched = 0; + } + dc->dc_reblock = reblock; + dc->dc_switched = switched; + dc->dc_srate = srate; + dc->dc_vecsize = vecsize; + dc->dc_calcsize = calcsize; + + /* if we're reblocking or switched, we now have to create output + signals to fill in for the "borrowed" ones we have now. This + is also possibly true even if we're not blocked/switched, in + the case that there was a signal loop. But we don't know this + yet. */ + + if (dc->dc_iosigs && (switched || reblock)) + { + t_signal **sigp; + for (i = 0, sigp = dc->dc_iosigs + dc->dc_ninlets; i < dc->dc_noutlets; + i++, sigp++) + { + if ((*sigp)->s_isborrowed && !(*sigp)->s_borrowedfrom) + { + signal_setborrowed(*sigp, + signal_new(parent_vecsize, parent_srate)); + (*sigp)->s_refcount++; + + if (THIS->u_loud) post("set %lx->%lx", *sigp, + (*sigp)->s_borrowedfrom); + } + } + } + + if (THIS->u_loud) + post("reblock %d, switched %d", reblock, switched); + + /* schedule prologs for inlets and outlets. If the "reblock" flag + is set, an inlet will put code on the DSP chain to copy its input + into an internal buffer here, before any unit generators' DSP code + gets scheduled. If we don't "reblock", inlets will need to get + pointers to their corresponding inlets/outlets on the box we're inside, + if any. Outlets will also need pointers, unless we're switched, in + which case outlet epilog code will kick in. */ + + for (u = dc->dc_ugenlist; u; u = u->u_next) + { + t_pd *zz = &u->u_obj->ob_pd; + t_signal **insigs = dc->dc_iosigs, **outsigs = dc->dc_iosigs; + if (outsigs) outsigs += dc->dc_ninlets; + + if (pd_class(zz) == vinlet_class) + vinlet_dspprolog((struct _vinlet *)zz, + dc->dc_iosigs, vecsize, calcsize, THIS->u_phase, period, frequency, + downsample, upsample, reblock, switched); + else if (pd_class(zz) == voutlet_class) + voutlet_dspprolog((struct _voutlet *)zz, + outsigs, vecsize, calcsize, THIS->u_phase, period, frequency, + downsample, upsample, reblock, switched); + } + chainblockbegin = THIS->u_dspchainsize; + + if (blk && (reblock || switched)) /* add the block DSP prolog */ + { + dsp_add(block_prolog, 1, blk); + blk->x_chainonset = THIS->u_dspchainsize - 1; + } + /* Initialize for sorting */ + for (u = dc->dc_ugenlist; u; u = u->u_next) + { + u->u_done = 0; + for (uout = u->u_out, i = u->u_nout; i--; uout++) + uout->o_nsent = 0; + for (uin = u->u_in, i = u->u_nin; i--; uin++) + uin->i_ngot = 0, uin->i_signal = 0; + } + + /* Do the sort */ + + for (u = dc->dc_ugenlist; u; u = u->u_next) + { + /* check that we have no connected signal inlets */ + if (u->u_done) continue; + for (uin = u->u_in, i = u->u_nin; i--; uin++) + if (uin->i_nconnect) goto next; + + ugen_doit(dc, u); + next: ; + } + + /* check for a DSP loop, which is evidenced here by the presence + of ugens not yet scheduled. */ + + for (u = dc->dc_ugenlist; u; u = u->u_next) + if (!u->u_done) + { + t_signal **sigp; + pd_error(u->u_obj, + "DSP loop detected (some tilde objects not scheduled)"); + /* this might imply that we have unfilled "borrowed" outputs + which we'd better fill in now. */ + for (i = 0, sigp = dc->dc_iosigs + dc->dc_ninlets; i < dc->dc_noutlets; + i++, sigp++) + { + if ((*sigp)->s_isborrowed && !(*sigp)->s_borrowedfrom) + { + t_signal *s3 = signal_new(parent_vecsize, parent_srate); + signal_setborrowed(*sigp, s3); + (*sigp)->s_refcount++; + dsp_add_zero(s3->s_vec, s3->s_n); + if (THIS->u_loud) + post("oops, belatedly set %lx->%lx", *sigp, + (*sigp)->s_borrowedfrom); + } + } + break; /* don't need to keep looking. */ + } + + if (blk && (reblock || switched)) /* add block DSP epilog */ + dsp_add(block_epilog, 1, blk); + chainblockend = THIS->u_dspchainsize; + + /* add epilogs for outlets. */ + + for (u = dc->dc_ugenlist; u; u = u->u_next) + { + t_pd *zz = &u->u_obj->ob_pd; + if (pd_class(zz) == voutlet_class) + { + t_signal **iosigs = dc->dc_iosigs; + if (iosigs) iosigs += dc->dc_ninlets; + voutlet_dspepilog((struct _voutlet *)zz, + iosigs, vecsize, calcsize, THIS->u_phase, period, frequency, + downsample, upsample, reblock, switched); + } + } + + chainafterall = THIS->u_dspchainsize; + if (blk) + { + blk->x_blocklength = chainblockend - chainblockbegin; + blk->x_epiloglength = chainafterall - chainblockend; + blk->x_reblock = reblock; + } + + if (THIS->u_loud) + { + t_int *ip; + if (!dc->dc_parentcontext) + for (i = THIS->u_dspchainsize, ip = THIS->u_dspchain; + i--; ip++) + post("chain %lx", *ip); + post("... ugen_done_graph done."); + } + /* now delete everything. */ + while (dc->dc_ugenlist) + { + for (uout = dc->dc_ugenlist->u_out, n = dc->dc_ugenlist->u_nout; + n--; uout++) + { + oc = uout->o_connections; + while (oc) + { + oc2 = oc->oc_next; + freebytes(oc, sizeof *oc); + oc = oc2; + } + } + freebytes(dc->dc_ugenlist->u_out, dc->dc_ugenlist->u_nout * + sizeof (*dc->dc_ugenlist->u_out)); + freebytes(dc->dc_ugenlist->u_in, dc->dc_ugenlist->u_nin * + sizeof(*dc->dc_ugenlist->u_in)); + u = dc->dc_ugenlist; + dc->dc_ugenlist = u->u_next; + freebytes(u, sizeof *u); + } + if (THIS->u_context == dc) + THIS->u_context = dc->dc_parentcontext; + else bug("THIS->u_context"); + freebytes(dc, sizeof(*dc)); + +} + +t_signal *ugen_getiosig(int index, int inout) +{ + if (!THIS->u_context) bug("ugen_getiosig"); + if (THIS->u_context->dc_toplevel) return (0); + if (inout) index += THIS->u_context->dc_ninlets; + return (THIS->u_context->dc_iosigs[index]); +} + +/* ------------------------ samplerate~~ -------------------------- */ + +static t_class *samplerate_tilde_class; + +typedef struct _samplerate +{ + t_object x_obj; + t_float x_sr; + t_canvas *x_canvas; +} t_samplerate; + +void *canvas_getblock(t_class *blockclass, t_canvas **canvasp); + +static void samplerate_tilde_bang(t_samplerate *x) +{ + t_float srate = sys_getsr(); + t_canvas *canvas = x->x_canvas; + while (canvas) + { + t_block *b = (t_block *)canvas_getblock(block_class, &canvas); + if (b) + srate *= (t_float)(b->x_upsample) / (t_float)(b->x_downsample); + } + outlet_float(x->x_obj.ob_outlet, srate); +} + +static void *samplerate_tilde_new(t_symbol *s) +{ + t_samplerate *x = (t_samplerate *)pd_new(samplerate_tilde_class); + outlet_new(&x->x_obj, &s_float); + x->x_canvas = canvas_getcurrent(); + return (x); +} + +static void samplerate_tilde_setup(void) +{ + samplerate_tilde_class = class_new(gensym("samplerate~"), + (t_newmethod)samplerate_tilde_new, 0, sizeof(t_samplerate), 0, 0); + class_addbang(samplerate_tilde_class, samplerate_tilde_bang); +} + +/* -------------------- setup routine -------------------------- */ + +void d_ugen_setup(void) +{ + block_tilde_setup(); + samplerate_tilde_setup(); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/g_all_guis.c b/ports/camomile/source/LibPd/pure-data/src/g_all_guis.c new file mode 100644 index 00000000..6488bce3 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_all_guis.c @@ -0,0 +1,786 @@ +/* Copyright (c) 1997-1999 Miller Puckette. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */ +/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */ + + +#include +#include +#include +#include +#include "m_pd.h" +#include "g_canvas.h" + +#include "g_all_guis.h" +#include + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +#ifdef _WIN32 +#include +#else +#include +#endif + +/* #define GGEE_HSLIDER_COMPATIBLE */ + +/*------------------ global variables -------------------------*/ + +int iemgui_color_hex[]= +{ + 16579836, 10526880, 4210752, 16572640, 16572608, + 16579784, 14220504, 14220540, 14476540, 16308476, + 14737632, 8158332, 2105376, 16525352, 16559172, + 15263784, 1370132, 2684148, 3952892, 16003312, + 12369084, 6316128, 0, 9177096, 5779456, + 7874580, 2641940, 17488, 5256, 5767248 +}; + +int iemgui_vu_db2i[]= +{ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9,10,10,10,10,10, + 11,11,11,11,11,12,12,12,12,12, + 13,13,13,13,14,14,14,14,15,15, + 15,15,16,16,16,16,17,17,17,18, + 18,18,19,19,19,20,20,20,21,21, + 22,22,23,23,24,24,25,26,27,28, + 29,30,31,32,33,33,34,34,35,35, + 36,36,37,37,37,38,38,38,39,39, + 39,39,39,39,40,40 +}; + +int iemgui_vu_col[]= +{ + 0,17,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 15,15,15,15,15,15,15,15,15,15,14,14,13,13,13,13,13,13,13,13,13,13,13,19,19,19 +}; + +char *iemgui_vu_scale_str[]= +{ + "", + "<-99", + "", + "", + "", + "-50", + "", + "", + "", + "-30", + "", + "", + "", + "-20", + "", + "", + "", + "-12", + "", + "", + "", + "-6", + "", + "", + "", + "-2", + "", + "", + "", + "-0dB", + "", + "", + "", + "+2", + "", + "", + "", + "+6", + "", + "", + "", + ">+12", + "", + "", + "", + "", + "", +}; + + +/*------------------ global functions -------------------------*/ + + +int iemgui_clip_size(int size) +{ + if(size < IEM_GUI_MINSIZE) + size = IEM_GUI_MINSIZE; + return(size); +} + +int iemgui_clip_font(int size) +{ + if(size < IEM_FONT_MINSIZE) + size = IEM_FONT_MINSIZE; + return(size); +} + +int iemgui_modulo_color(int col) +{ + while(col >= IEM_GUI_MAX_COLOR) + col -= IEM_GUI_MAX_COLOR; + while(col < 0) + col += IEM_GUI_MAX_COLOR; + return(col); +} + +t_symbol *iemgui_dollar2raute(t_symbol *s) +{ + char buf[MAXPDSTRING+1], *s1, *s2; + if (strlen(s->s_name) >= MAXPDSTRING) + return (s); + for (s1 = s->s_name, s2 = buf; ; s1++, s2++) + { + if (*s1 == '$') + *s2 = '#'; + else if (!(*s2 = *s1)) + break; + } + return(gensym(buf)); +} + +t_symbol *iemgui_raute2dollar(t_symbol *s) +{ + char buf[MAXPDSTRING+1], *s1, *s2; + if (strlen(s->s_name) >= MAXPDSTRING) + return (s); + for (s1 = s->s_name, s2 = buf; ; s1++, s2++) + { + if (*s1 == '#') + *s2 = '$'; + else if (!(*s2 = *s1)) + break; + } + return(gensym(buf)); +} + +void iemgui_verify_snd_ne_rcv(t_iemgui *iemgui) +{ + iemgui->x_fsf.x_put_in2out = 1; + if(iemgui->x_fsf.x_snd_able && iemgui->x_fsf.x_rcv_able) + { + if(!strcmp(iemgui->x_snd->s_name, iemgui->x_rcv->s_name)) + iemgui->x_fsf.x_put_in2out = 0; + } +} + +t_symbol *iemgui_new_dogetname(t_iemgui *iemgui, int indx, t_atom *argv) +{ + if (IS_A_SYMBOL(argv, indx)) + return (atom_getsymbolarg(indx, 100000, argv)); + else if (IS_A_FLOAT(argv, indx)) + { + char str[80]; + sprintf(str, "%d", (int)atom_getfloatarg(indx, 100000, argv)); + return (gensym(str)); + } + else return (gensym("empty")); +} + +void iemgui_new_getnames(t_iemgui *iemgui, int indx, t_atom *argv) +{ + if (argv) + { + iemgui->x_snd = iemgui_new_dogetname(iemgui, indx, argv); + iemgui->x_rcv = iemgui_new_dogetname(iemgui, indx+1, argv); + iemgui->x_lab = iemgui_new_dogetname(iemgui, indx+2, argv); + } + else iemgui->x_snd = iemgui->x_rcv = iemgui->x_lab = gensym("empty"); + iemgui->x_snd_unexpanded = iemgui->x_rcv_unexpanded = + iemgui->x_lab_unexpanded = 0; + iemgui->x_binbufindex = indx; + iemgui->x_labelbindex = indx + 3; +} + + /* convert symbols in "$" form to the expanded symbols */ +void iemgui_all_dollararg2sym(t_iemgui *iemgui, t_symbol **srlsym) +{ + /* save unexpanded ones for later */ + iemgui->x_snd_unexpanded = srlsym[0]; + iemgui->x_rcv_unexpanded = srlsym[1]; + iemgui->x_lab_unexpanded = srlsym[2]; + srlsym[0] = canvas_realizedollar(iemgui->x_glist, srlsym[0]); + srlsym[1] = canvas_realizedollar(iemgui->x_glist, srlsym[1]); + srlsym[2] = canvas_realizedollar(iemgui->x_glist, srlsym[2]); +} + + /* initialize a single symbol in unexpanded form. We reach into the + binbuf to grab them; if there's nothing there, set it to the + fallback; if still nothing, set to "empty". */ +static void iemgui_init_sym2dollararg(t_iemgui *iemgui, t_symbol **symp, + int indx, t_symbol *fallback) +{ + if (!*symp) + { + t_binbuf *b = iemgui->x_obj.ob_binbuf; + if (binbuf_getnatom(b) > indx) + { + char buf[80]; + atom_string(binbuf_getvec(b) + indx, buf, 80); + *symp = gensym(buf); + } + else if (fallback) + *symp = fallback; + else *symp = gensym("empty"); + } +} + + /* get the unexpanded versions of the symbols; initialize them if + necessary. */ +void iemgui_all_sym2dollararg(t_iemgui *iemgui, t_symbol **srlsym) +{ + iemgui_init_sym2dollararg(iemgui, &iemgui->x_snd_unexpanded, + iemgui->x_binbufindex+1, iemgui->x_snd); + iemgui_init_sym2dollararg(iemgui, &iemgui->x_rcv_unexpanded, + iemgui->x_binbufindex+2, iemgui->x_rcv); + iemgui_init_sym2dollararg(iemgui, &iemgui->x_lab_unexpanded, + iemgui->x_labelbindex, iemgui->x_lab); + srlsym[0] = iemgui->x_snd_unexpanded; + srlsym[1] = iemgui->x_rcv_unexpanded; + srlsym[2] = iemgui->x_lab_unexpanded; +} + +static t_symbol* color2symbol(int col) { + const int compat = (pd_compatibilitylevel < 48)?1: + /* FIXXME: for Pd>=0.48, the default compatibility mode should be OFF */ + 1; + + char colname[MAXPDSTRING]; + colname[0] = colname[MAXPDSTRING-1] = 0; + + if (compat) + { + /* compatibility with Pd<=0.47: saves colors as numbers with limited resolution */ + int col2 = -1 - (((0xfc0000 & col) >> 6)|((0xfc00 & col) >> 4)|((0xfc & col) >> 2)); + snprintf(colname, MAXPDSTRING-1, "%d", col2); + } else { + snprintf(colname, MAXPDSTRING-1, "#%06x", col); + } + return gensym(colname); +} + +void iemgui_all_col2save(t_iemgui *iemgui, t_symbol**bflcol) +{ + bflcol[0] = color2symbol(iemgui->x_bcol); + bflcol[1] = color2symbol(iemgui->x_fcol); + bflcol[2] = color2symbol(iemgui->x_lcol); +} + +static int iemgui_getcolorarg(int index, int argc, t_atom*argv) +{ + if(index < 0 || index >= argc) + return 0; + if(IS_A_FLOAT(argv,index)) + return atom_getfloatarg(index, argc, argv); + if(IS_A_SYMBOL(argv,index)) + { + t_symbol*s=atom_getsymbolarg(index, argc, argv); + if ('#' == s->s_name[0]) + return (int)strtol(s->s_name+1, 0, 16); + } + return 0; +} + +static int colfromatomload(t_atom*colatom) +{ + int color; + /* old-fashioned color argument, either a number or symbol + evaluating to an integer */ + if (colatom->a_type == A_FLOAT) + color = atom_getfloat(colatom); + else if (colatom->a_type == A_SYMBOL && + (isdigit(colatom->a_w.w_symbol->s_name[0]) || + colatom->a_w.w_symbol->s_name[0] == '-')) + color = atoi(colatom->a_w.w_symbol->s_name); + + /* symbolic color */ + else return (iemgui_getcolorarg(0, 1, colatom)); + if (color < 0) + { + color = -1 - color; + color = ((color & 0x3f000) << 6)|((color & 0xfc0) << 4)| + ((color & 0x3f) << 2); + } + else + { + color = iemgui_modulo_color(color); + color = iemgui_color_hex[color]; + } + return (color); +} + +void iemgui_all_loadcolors(t_iemgui *iemgui, t_atom*bcol, t_atom*fcol, t_atom*lcol) +{ + if(bcol)iemgui->x_bcol = colfromatomload(bcol); + if(fcol)iemgui->x_fcol = colfromatomload(fcol); + if(lcol)iemgui->x_lcol = colfromatomload(lcol); +} + +int iemgui_compatible_colorarg(int index, int argc, t_atom* argv) +{ + if (index < 0 || index >= argc) + return 0; + if(IS_A_FLOAT(argv,index)) + { + int col=atom_getfloatarg(index, argc, argv); + if(col >= 0) + { + int idx = iemgui_modulo_color(col); + return(iemgui_color_hex[(idx)]); + } + else + return((-1 -col)&0xffffff); + } + return iemgui_getcolorarg(index, argc, argv); +} + +void iemgui_all_dollar2raute(t_symbol **srlsym) +{ + srlsym[0] = iemgui_dollar2raute(srlsym[0]); + srlsym[1] = iemgui_dollar2raute(srlsym[1]); + srlsym[2] = iemgui_dollar2raute(srlsym[2]); +} + +void iemgui_all_raute2dollar(t_symbol **srlsym) +{ + srlsym[0] = iemgui_raute2dollar(srlsym[0]); + srlsym[1] = iemgui_raute2dollar(srlsym[1]); + srlsym[2] = iemgui_raute2dollar(srlsym[2]); +} + +void iemgui_send(void *x, t_iemgui *iemgui, t_symbol *s) +{ + t_symbol *snd; + int pargc, tail_len, nth_arg, sndable=1, oldsndrcvable=0; + t_atom *pargv; + + if(iemgui->x_fsf.x_rcv_able) + oldsndrcvable += IEM_GUI_OLD_RCV_FLAG; + if(iemgui->x_fsf.x_snd_able) + oldsndrcvable += IEM_GUI_OLD_SND_FLAG; + + if(!strcmp(s->s_name, "empty")) sndable = 0; + snd = iemgui_raute2dollar(s); + iemgui->x_snd_unexpanded = snd; + iemgui->x_snd = snd = canvas_realizedollar(iemgui->x_glist, snd); + iemgui->x_fsf.x_snd_able = sndable; + iemgui_verify_snd_ne_rcv(iemgui); + (*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_IO + oldsndrcvable); +} + +void iemgui_receive(void *x, t_iemgui *iemgui, t_symbol *s) +{ + t_symbol *rcv; + int pargc, tail_len, nth_arg, rcvable=1, oldsndrcvable=0; + t_atom *pargv; + + if(iemgui->x_fsf.x_rcv_able) + oldsndrcvable += IEM_GUI_OLD_RCV_FLAG; + if(iemgui->x_fsf.x_snd_able) + oldsndrcvable += IEM_GUI_OLD_SND_FLAG; + + if(!strcmp(s->s_name, "empty")) rcvable = 0; + rcv = iemgui_raute2dollar(s); + iemgui->x_rcv_unexpanded = rcv; + rcv = canvas_realizedollar(iemgui->x_glist, rcv); + if(rcvable) + { + if(strcmp(rcv->s_name, iemgui->x_rcv->s_name)) + { + if(iemgui->x_fsf.x_rcv_able) + pd_unbind(&iemgui->x_obj.ob_pd, iemgui->x_rcv); + iemgui->x_rcv = rcv; + pd_bind(&iemgui->x_obj.ob_pd, iemgui->x_rcv); + } + } + else if(!rcvable && iemgui->x_fsf.x_rcv_able) + { + pd_unbind(&iemgui->x_obj.ob_pd, iemgui->x_rcv); + iemgui->x_rcv = rcv; + } + iemgui->x_fsf.x_rcv_able = rcvable; + iemgui_verify_snd_ne_rcv(iemgui); + (*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_IO + oldsndrcvable); +} + +void iemgui_label(void *x, t_iemgui *iemgui, t_symbol *s) +{ + t_symbol *old; + int pargc, tail_len, nth_arg; + t_atom *pargv; + + /* tb: fix for empty label { */ + if (s == gensym("")) + s = gensym("empty"); + /* tb } */ + + old = iemgui->x_lab; + iemgui->x_lab_unexpanded = iemgui_raute2dollar(s); + iemgui->x_lab = canvas_realizedollar(iemgui->x_glist, iemgui->x_lab_unexpanded); + + if(glist_isvisible(iemgui->x_glist) && iemgui->x_lab != old) + sys_vgui(".x%lx.c itemconfigure %lxLABEL -text {%s} \n", + glist_getcanvas(iemgui->x_glist), x, + strcmp(s->s_name, "empty")?iemgui->x_lab->s_name:""); +} + +void iemgui_label_pos(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av) +{ + int zoom = glist_getzoom(iemgui->x_glist); + iemgui->x_ldx = (int)atom_getfloatarg(0, ac, av); + iemgui->x_ldy = (int)atom_getfloatarg(1, ac, av); + if(glist_isvisible(iemgui->x_glist)) + sys_vgui(".x%lx.c coords %lxLABEL %d %d\n", + glist_getcanvas(iemgui->x_glist), x, + text_xpix((t_object *)x, iemgui->x_glist) + iemgui->x_ldx*zoom, + text_ypix((t_object *)x, iemgui->x_glist) + iemgui->x_ldy*zoom); +} + +void iemgui_label_font(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av) +{ + int zoom = glist_getzoom(iemgui->x_glist); + int f = (int)atom_getfloatarg(0, ac, av); + + if(f == 1) strcpy(iemgui->x_font, "helvetica"); + else if(f == 2) strcpy(iemgui->x_font, "times"); + else + { + f = 0; + strcpy(iemgui->x_font, sys_font); + } + iemgui->x_fsf.x_font_style = f; + f = (int)atom_getfloatarg(1, ac, av); + if(f < 4) + f = 4; + iemgui->x_fontsize = f; + if(glist_isvisible(iemgui->x_glist)) + sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s}\n", + glist_getcanvas(iemgui->x_glist), x, iemgui->x_font, + iemgui->x_fontsize*zoom, sys_fontweight); +} + +void iemgui_size(void *x, t_iemgui *iemgui) +{ + if(glist_isvisible(iemgui->x_glist)) + { + (*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(iemgui->x_glist, (t_text*)x); + } +} + +void iemgui_delta(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av) +{ + int zoom = glist_getzoom(iemgui->x_glist); + iemgui->x_obj.te_xpix += (int)atom_getfloatarg(0, ac, av)*zoom; + iemgui->x_obj.te_ypix += (int)atom_getfloatarg(1, ac, av)*zoom; + if(glist_isvisible(iemgui->x_glist)) + { + (*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(iemgui->x_glist, (t_text*)x); + } +} + +void iemgui_pos(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av) +{ + int zoom = glist_getzoom(iemgui->x_glist); + iemgui->x_obj.te_xpix = (int)atom_getfloatarg(0, ac, av)*zoom; + iemgui->x_obj.te_ypix = (int)atom_getfloatarg(1, ac, av)*zoom; + if(glist_isvisible(iemgui->x_glist)) + { + (*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(iemgui->x_glist, (t_text*)x); + } +} + +void iemgui_color(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av) +{ + if (ac >= 1) + iemgui->x_bcol = iemgui_compatible_colorarg(0, ac, av); + if (ac == 2 && pd_compatibilitylevel < 47) + /* old versions of Pd updated foreground and label color + if only two args; now we do it more coherently. */ + iemgui->x_lcol = iemgui_compatible_colorarg(1, ac, av); + else if (ac >= 2) + iemgui->x_fcol = iemgui_compatible_colorarg(1, ac, av); + if (ac >= 3) + iemgui->x_lcol = iemgui_compatible_colorarg(2, ac, av); + if(glist_isvisible(iemgui->x_glist)) + (*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_CONFIG); +} + +void iemgui_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_iemgui *x = (t_iemgui *)z; + + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + (*x->x_draw)((void *)z, glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(glist, (t_text *)z); +} + +void iemgui_select(t_gobj *z, t_glist *glist, int selected) +{ + t_iemgui *x = (t_iemgui *)z; + + x->x_fsf.x_selected = selected; + (*x->x_draw)((void *)z, glist, IEM_GUI_DRAW_MODE_SELECT); +} + +void iemgui_delete(t_gobj *z, t_glist *glist) +{ + canvas_deletelinesfor(glist, (t_text *)z); +} + +void iemgui_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_iemgui *x = (t_iemgui *)z; + + if (vis) + (*x->x_draw)((void *)z, glist, IEM_GUI_DRAW_MODE_NEW); + else + { + (*x->x_draw)((void *)z, glist, IEM_GUI_DRAW_MODE_ERASE); + sys_unqueuegui(z); + } +} + +void iemgui_save(t_iemgui *iemgui, t_symbol **srl, t_symbol**bflcol) +{ + srl[0] = iemgui->x_snd; + srl[1] = iemgui->x_rcv; + srl[2] = iemgui->x_lab; + iemgui_all_sym2dollararg(iemgui, srl); + iemgui_all_col2save(iemgui, bflcol); +} + + /* inform GUIs that glist's zoom is about to change. The glist will + take care of x,y locations but we have to adjust width and height */ +void iemgui_zoom(t_iemgui *iemgui, t_floatarg zoom) +{ + int oldzoom = iemgui->x_glist->gl_zoom; + if (oldzoom < 1) + oldzoom = 1; + iemgui->x_w = (int)(iemgui->x_w)/oldzoom*(int)zoom; + iemgui->x_h = (int)(iemgui->x_h)/oldzoom*(int)zoom; +} + + /* when creating a new GUI from menu onto a zoomed canvas, pretend to + change the canvas's zoom so we'll get properly sized */ +void iemgui_newzoom(t_iemgui *iemgui) +{ + if (iemgui->x_glist->gl_zoom != 1) + { + int newzoom = iemgui->x_glist->gl_zoom; + iemgui->x_glist->gl_zoom = 1; + iemgui_zoom(iemgui, (t_floatarg)newzoom); + iemgui->x_glist->gl_zoom = newzoom; + } +} + +void iemgui_properties(t_iemgui *iemgui, t_symbol **srl) +{ + srl[0] = iemgui->x_snd; + srl[1] = iemgui->x_rcv; + srl[2] = iemgui->x_lab; + iemgui_all_sym2dollararg(iemgui, srl); + iemgui_all_dollar2raute(srl); +} + +int iemgui_dialog(t_iemgui *iemgui, t_symbol **srl, int argc, t_atom *argv) +{ + char str[144]; + int init = (int)atom_getfloatarg(5, argc, argv); + int ldx = (int)atom_getfloatarg(10, argc, argv); + int ldy = (int)atom_getfloatarg(11, argc, argv); + int f = (int)atom_getfloatarg(12, argc, argv); + int fs = (int)atom_getfloatarg(13, argc, argv); + int bcol = (int)iemgui_getcolorarg(14, argc, argv); + int fcol = (int)iemgui_getcolorarg(15, argc, argv); + int lcol = (int)iemgui_getcolorarg(16, argc, argv); + int sndable=1, rcvable=1, oldsndrcvable=0; + + if(iemgui->x_fsf.x_rcv_able) + oldsndrcvable += IEM_GUI_OLD_RCV_FLAG; + if(iemgui->x_fsf.x_snd_able) + oldsndrcvable += IEM_GUI_OLD_SND_FLAG; + if(IS_A_SYMBOL(argv,7)) + srl[0] = atom_getsymbolarg(7, argc, argv); + else if(IS_A_FLOAT(argv,7)) + { + sprintf(str, "%d", (int)atom_getfloatarg(7, argc, argv)); + srl[0] = gensym(str); + } + if(IS_A_SYMBOL(argv,8)) + srl[1] = atom_getsymbolarg(8, argc, argv); + else if(IS_A_FLOAT(argv,8)) + { + sprintf(str, "%d", (int)atom_getfloatarg(8, argc, argv)); + srl[1] = gensym(str); + } + if(IS_A_SYMBOL(argv,9)) + srl[2] = atom_getsymbolarg(9, argc, argv); + else if(IS_A_FLOAT(argv,9)) + { + sprintf(str, "%d", (int)atom_getfloatarg(9, argc, argv)); + srl[2] = gensym(str); + } + if(init != 0) init = 1; + iemgui->x_isa.x_loadinit = init; + if(!strcmp(srl[0]->s_name, "empty")) sndable = 0; + if(!strcmp(srl[1]->s_name, "empty")) rcvable = 0; + iemgui_all_raute2dollar(srl); + iemgui_all_dollararg2sym(iemgui, srl); + if(rcvable) + { + if(strcmp(srl[1]->s_name, iemgui->x_rcv->s_name)) + { + if(iemgui->x_fsf.x_rcv_able) + pd_unbind(&iemgui->x_obj.ob_pd, iemgui->x_rcv); + iemgui->x_rcv = srl[1]; + pd_bind(&iemgui->x_obj.ob_pd, iemgui->x_rcv); + } + } + else if(!rcvable && iemgui->x_fsf.x_rcv_able) + { + pd_unbind(&iemgui->x_obj.ob_pd, iemgui->x_rcv); + iemgui->x_rcv = srl[1]; + } + iemgui->x_snd = srl[0]; + iemgui->x_fsf.x_snd_able = sndable; + iemgui->x_fsf.x_rcv_able = rcvable; + iemgui->x_lcol = lcol & 0xffffff; + iemgui->x_fcol = fcol & 0xffffff; + iemgui->x_bcol = bcol & 0xffffff; + iemgui->x_lab = srl[2]; + iemgui->x_ldx = ldx; + iemgui->x_ldy = ldy; + if(f == 1) strcpy(iemgui->x_font, "helvetica"); + else if(f == 2) strcpy(iemgui->x_font, "times"); + else + { + f = 0; + strcpy(iemgui->x_font, sys_font); + } + iemgui->x_fsf.x_font_style = f; + if(fs < 4) + fs = 4; + iemgui->x_fontsize = fs; + iemgui_verify_snd_ne_rcv(iemgui); + canvas_dirty(iemgui->x_glist, 1); + return(oldsndrcvable); +} + +/* pre-0.46 the flags were 1 for 'loadinit' and 1<<20 for 'scale'. +Starting in 0.46, take either 1<<20 or 1<<1 for 'scale' and save to both +bits (so that old versions can read files we write). In the future (2015?) +we can stop writing the annoying 1<<20 bit. */ +#define LOADINIT 1 +#define SCALE 2 +#define SCALEBIS (1<<20) + +void iem_inttosymargs(t_iem_init_symargs *symargp, int n) +{ + memset(symargp, 0, sizeof(*symargp)); + symargp->x_loadinit = ((n & LOADINIT) != 0); + symargp->x_scale = ((n & SCALE) || (n & SCALEBIS)) ; + symargp->x_flashed = 0; + symargp->x_locked = 0; +} + +int iem_symargstoint(t_iem_init_symargs *symargp) +{ + return ((symargp->x_loadinit ? LOADINIT : 0) | + (symargp->x_scale ? (SCALE | SCALEBIS) : 0)); +} + +void iem_inttofstyle(t_iem_fstyle_flags *fstylep, int n) +{ + memset(fstylep, 0, sizeof(*fstylep)); + fstylep->x_font_style = (n >> 0); + fstylep->x_shiftdown = 0; + fstylep->x_selected = 0; + fstylep->x_finemoved = 0; + fstylep->x_put_in2out = 0; + fstylep->x_change = 0; + fstylep->x_thick = 0; + fstylep->x_lin0_log1 = 0; + fstylep->x_steady = 0; +} + +int iem_fstyletoint(t_iem_fstyle_flags *fstylep) +{ + return ((fstylep->x_font_style << 0) & 63); +} + + /* for compatibility with pre-0.47 unofficial IEM GUIS like "knob". */ +void iemgui_all_colfromload(t_iemgui *iemgui, int *bflcol) +{ + static int warned; + if (!warned) + { + post("warning:\ +external GUI object uses obsolete Pd function iemgui_all_colfromload()"); + warned = 1; + } + if(bflcol[0] < 0) + { + bflcol[0] = -1 - bflcol[0]; + iemgui->x_bcol = ((bflcol[0] & 0x3f000) << 6)|((bflcol[0] & 0xfc0) << 4)| + ((bflcol[0] & 0x3f) << 2); + } + else + { + bflcol[0] = iemgui_modulo_color(bflcol[0]); + iemgui->x_bcol = iemgui_color_hex[bflcol[0]]; + } + if(bflcol[1] < 0) + { + bflcol[1] = -1 - bflcol[1]; + iemgui->x_fcol = ((bflcol[1] & 0x3f000) << 6)|((bflcol[1] & 0xfc0) << 4)| + ((bflcol[1] & 0x3f) << 2); + } + else + { + bflcol[1] = iemgui_modulo_color(bflcol[1]); + iemgui->x_fcol = iemgui_color_hex[bflcol[1]]; + } + if(bflcol[2] < 0) + { + bflcol[2] = -1 - bflcol[2]; + iemgui->x_lcol = ((bflcol[2] & 0x3f000) << 6)|((bflcol[2] & 0xfc0) << 4)| + ((bflcol[2] & 0x3f) << 2); + } + else + { + bflcol[2] = iemgui_modulo_color(bflcol[2]); + iemgui->x_lcol = iemgui_color_hex[bflcol[2]]; + } +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/g_all_guis.h b/ports/camomile/source/LibPd/pure-data/src/g_all_guis.h new file mode 100644 index 00000000..45a2811b --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_all_guis.h @@ -0,0 +1,324 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ +/* g_7_guis.h written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */ + +#define IEM_GUI_COLNR_WHITE 0 +#define IEM_GUI_COLNR_ML_GREY 1 +#define IEM_GUI_COLNR_D_GREY 2 +#define IEM_GUI_COLNR_L_RED 3 +#define IEM_GUI_COLNR_L_ORANGE 4 +#define IEM_GUI_COLNR_L_YELLOW 5 +#define IEM_GUI_COLNR_L_GREEN 6 +#define IEM_GUI_COLNR_L_CYAN 7 +#define IEM_GUI_COLNR_L_BLUE 8 +#define IEM_GUI_COLNR_L_MAGENTA 9 + +#define IEM_GUI_COLNR_LL_GREY 10 +#define IEM_GUI_COLNR_M_GREY 11 +#define IEM_GUI_COLNR_DD_GREY 12 +#define IEM_GUI_COLNR_RED 13 +#define IEM_GUI_COLNR_ORANGE 14 +#define IEM_GUI_COLNR_YELLOW 15 +#define IEM_GUI_COLNR_GREEN 16 +#define IEM_GUI_COLNR_CYAN 17 +#define IEM_GUI_COLNR_BLUE 18 +#define IEM_GUI_COLNR_MAGENTA 19 + +#define IEM_GUI_COLNR_L_GREY 20 +#define IEM_GUI_COLNR_MD_GREY 21 +#define IEM_GUI_COLNR_BLACK 22 +#define IEM_GUI_COLNR_D_RED 23 +#define IEM_GUI_COLNR_D_ORANGE 24 +#define IEM_GUI_COLNR_D_YELLOW 25 +#define IEM_GUI_COLNR_D_GREEN 26 +#define IEM_GUI_COLNR_D_CYAN 27 +#define IEM_GUI_COLNR_D_BLUE 28 +#define IEM_GUI_COLNR_D_MAGENTA 29 + +#define IEM_GUI_COLOR_SELECTED 255 +#define IEM_GUI_COLOR_NORMAL 0 + +#define IEM_GUI_MAX_COLOR 30 + +#define IEM_GUI_DEFAULTSIZE 15 +#define IEM_GUI_MINSIZE 8 +#define IEM_GUI_MAXSIZE 1000 +#define IEM_SL_DEFAULTSIZE 128 +#define IEM_SL_MINSIZE 2 +#define IEM_FONT_MINSIZE 4 + +#define IEM_BNG_DEFAULTHOLDFLASHTIME 250 +#define IEM_BNG_DEFAULTBREAKFLASHTIME 50 +#define IEM_BNG_MINHOLDFLASHTIME 50 +#define IEM_BNG_MINBREAKFLASHTIME 10 + +#define IEM_VU_DEFAULTSIZE 3 +#define IEM_VU_LARGESMALL 2 +#define IEM_VU_MINSIZE 2 +#define IEM_VU_MAXSIZE 25 +#define IEM_VU_STEPS 40 + +#define IEM_VU_MINDB -99.9 +#define IEM_VU_MAXDB 12.0 +#define IEM_VU_OFFSET 100.0 + +#define IEM_RADIO_MAX 128 + +#define IEM_SYM_UNIQUE_SND 256 +#define IEM_SYM_UNIQUE_RCV 512 +#define IEM_SYM_UNIQUE_LAB 1024 +#define IEM_SYM_UNIQUE_ALL 1792 +#define IEM_FONT_STYLE_ALL 255 + +#define IEM_MAX_SYM_LEN 127 + +#define IEM_GUI_DRAW_MODE_UPDATE 0 +#define IEM_GUI_DRAW_MODE_MOVE 1 +#define IEM_GUI_DRAW_MODE_NEW 2 +#define IEM_GUI_DRAW_MODE_SELECT 3 +#define IEM_GUI_DRAW_MODE_ERASE 4 +#define IEM_GUI_DRAW_MODE_CONFIG 5 +#define IEM_GUI_DRAW_MODE_IO 6 + +#define IEM_GUI_IOHEIGHT 2 + +#define IS_A_POINTER(atom,index) ((atom+index)->a_type == A_POINTER) +#define IS_A_FLOAT(atom,index) ((atom+index)->a_type == A_FLOAT) +#define IS_A_SYMBOL(atom,index) ((atom+index)->a_type == A_SYMBOL) +#define IS_A_DOLLAR(atom,index) ((atom+index)->a_type == A_DOLLAR) +#define IS_A_DOLLSYM(atom,index) ((atom+index)->a_type == A_DOLLSYM) + +#define IEM_FSTYLE_FLAGS_ALL 0x007fffff +#define IEM_INIT_ARGS_ALL 0x01ffffff + +#define IEM_GUI_OLD_SND_FLAG 1 +#define IEM_GUI_OLD_RCV_FLAG 2 + +#define IEM_GUI_COLOR_EDITED 16711680 +#define IEMGUI_MAX_NUM_LEN 32 + +#define IEMGUI_ZOOM(x) ((x)->x_gui.x_glist->gl_zoom) + +typedef struct _iem_fstyle_flags +{ + unsigned int x_font_style:6; + unsigned int x_rcv_able:1; + unsigned int x_snd_able:1; + unsigned int x_lab_is_unique:1; + unsigned int x_rcv_is_unique:1; + unsigned int x_snd_is_unique:1; + unsigned int x_lab_arg_tail_len:6; + unsigned int x_lab_is_arg_num:6; + unsigned int x_shiftdown:1; + unsigned int x_selected:1; + unsigned int x_finemoved:1; + unsigned int x_put_in2out:1; + unsigned int x_change:1; + unsigned int x_thick:1; + unsigned int x_lin0_log1:1; + unsigned int x_steady:1; +} t_iem_fstyle_flags; + +typedef struct _iem_init_symargs +{ + unsigned int x_loadinit:1; + unsigned int x_rcv_arg_tail_len:6; + unsigned int x_snd_arg_tail_len:6; + unsigned int x_rcv_is_arg_num:6; + unsigned int x_snd_is_arg_num:6; + unsigned int x_scale:1; + unsigned int x_flashed:1; + unsigned int x_locked:1; +} t_iem_init_symargs; + +typedef void (*t_iemfunptr)(void *x, t_glist *glist, int mode); + +typedef struct _iemgui +{ + t_object x_obj; + t_glist *x_glist; + t_iemfunptr x_draw; + int x_h; + int x_w; + int x_ldx; + int x_ldy; + char x_font[MAXPDSTRING]; /* font names can be long! */ + t_iem_fstyle_flags x_fsf; + int x_fontsize; + t_iem_init_symargs x_isa; + int x_fcol; + int x_bcol; + int x_lcol; + t_symbol *x_snd; /* send symbol */ + t_symbol *x_rcv; /* receive */ + t_symbol *x_lab; /* label */ + t_symbol *x_snd_unexpanded; /* same 3, with '$' unexpanded */ + t_symbol *x_rcv_unexpanded; + t_symbol *x_lab_unexpanded; + int x_binbufindex; /* where in binbuf to find these */ + int x_labelbindex; /* where in binbuf to find label */ +} t_iemgui; + +typedef struct _bng +{ + t_iemgui x_gui; + int x_flashed; + int x_flashtime_break; + int x_flashtime_hold; + t_clock *x_clock_hld; + t_clock *x_clock_brk; + t_clock *x_clock_lck; + double x_lastflashtime; +} t_bng; + +typedef struct _hslider +{ + t_iemgui x_gui; + int x_pos; + int x_val; + int x_lin0_log1; + int x_steady; + double x_min; + double x_max; + double x_k; + t_float x_fval; +} t_hslider; + +typedef struct _hdial +{ + t_iemgui x_gui; + int x_on; + int x_on_old; /* LATER delete this; it's used for old version */ + int x_change; + int x_number; + int x_drawn; + t_float x_fval; + t_atom x_at[2]; +} t_hdial; + +typedef struct _toggle +{ + t_iemgui x_gui; + t_float x_on; + t_float x_nonzero; +} t_toggle; + +typedef struct _my_canvas +{ + t_iemgui x_gui; + t_atom x_at[3]; + int x_vis_w; + int x_vis_h; +} t_my_canvas; + +typedef struct _vslider +{ + t_iemgui x_gui; + int x_pos; + int x_val; + int x_lin0_log1; + int x_steady; + double x_min; + double x_max; + double x_k; + t_float x_fval; +} t_vslider; + +typedef struct _vu +{ + t_iemgui x_gui; + int x_led_size; + int x_peak; + int x_rms; + t_float x_fp; + t_float x_fr; + int x_scale; + void *x_out_rms; + void *x_out_peak; + unsigned int x_updaterms:1; + unsigned int x_updatepeak:1; +} t_vu; + +typedef struct _my_numbox +{ + t_iemgui x_gui; + t_clock *x_clock_reset; + t_clock *x_clock_wait; + double x_val; + double x_min; + double x_max; + double x_k; + int x_lin0_log1; + char x_buf[IEMGUI_MAX_NUM_LEN]; + int x_numwidth; + int x_log_height; +} t_my_numbox; + +typedef struct _vdial +{ + t_iemgui x_gui; + int x_on; + int x_on_old; + int x_change; + int x_number; + int x_drawn; + t_float x_fval; + t_atom x_at[2]; +} t_vdial; + +#define t_vradio t_vdial +#define t_hradio t_hdial + +extern int iemgui_color_hex[]; +extern int iemgui_vu_db2i[]; +extern int iemgui_vu_col[]; +extern char *iemgui_vu_scale_str[]; + +EXTERN int iemgui_clip_size(int size); +EXTERN int iemgui_clip_font(int size); +EXTERN t_symbol *iemgui_unique2dollarzero(t_symbol *s, int unique_num, int and_unique_flag); +EXTERN t_symbol *iemgui_sym2dollararg(t_symbol *s, int nth_arg, int tail_len); +EXTERN t_symbol *iemgui_dollarzero2unique(t_symbol *s, int unique_num); +EXTERN t_symbol *iemgui_dollararg2sym(t_symbol *s, int nth_arg, int tail_len, int pargc, t_atom *pargv); +EXTERN int iemgui_is_dollarzero(t_symbol *s); +EXTERN int iemgui_is_dollararg(t_symbol *s, int *tail_len); +EXTERN void iemgui_fetch_unique(t_iemgui *iemgui); +EXTERN void iemgui_fetch_parent_args(t_iemgui *iemgui, int *pargc, t_atom **pargv); +EXTERN void iemgui_verify_snd_ne_rcv(t_iemgui *iemgui); +EXTERN void iemgui_all_unique2dollarzero(t_iemgui *iemgui, t_symbol **srlsym); +EXTERN void iemgui_all_sym2dollararg(t_iemgui *iemgui, t_symbol **srlsym); +EXTERN void iemgui_all_dollarzero2unique(t_iemgui *iemgui, t_symbol **srlsym); +EXTERN t_symbol *iemgui_new_dogetname(t_iemgui *iemgui, int indx, t_atom *argv); +EXTERN void iemgui_new_getnames(t_iemgui *iemgui, int indx, t_atom *argv); +EXTERN void iemgui_all_dollararg2sym(t_iemgui *iemgui, t_symbol **srlsym); +EXTERN void iemgui_all_loadcolors(t_iemgui *iemgui, t_atom*bcol, t_atom*fcol, t_atom*lcol); +EXTERN void iemgui_all_dollar2raute(t_symbol **srlsym); +EXTERN void iemgui_all_raute2dollar(t_symbol **srlsym); +EXTERN void iemgui_send(void *x, t_iemgui *iemgui, t_symbol *s); +EXTERN void iemgui_receive(void *x, t_iemgui *iemgui, t_symbol *s); +EXTERN void iemgui_label(void *x, t_iemgui *iemgui, t_symbol *s); +EXTERN void iemgui_label_pos(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av); +EXTERN void iemgui_label_font(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av); +EXTERN void iemgui_size(void *x, t_iemgui *iemgui); +EXTERN void iemgui_delta(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av); +EXTERN void iemgui_pos(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av); +EXTERN void iemgui_color(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av); +EXTERN int iemgui_list(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av); +EXTERN void iemgui_displace(t_gobj *z, t_glist *glist, int dx, int dy); +EXTERN void iemgui_select(t_gobj *z, t_glist *glist, int selected); +EXTERN void iemgui_delete(t_gobj *z, t_glist *glist); +EXTERN void iemgui_vis(t_gobj *z, t_glist *glist, int vis); +EXTERN void iemgui_save(t_iemgui *iemgui, t_symbol **srl, t_symbol **bflcol); +EXTERN void iemgui_zoom(t_iemgui *iemgui, t_floatarg zoom); +EXTERN void iemgui_newzoom(t_iemgui *iemgui); +EXTERN void iemgui_properties(t_iemgui *iemgui, t_symbol **srl); +EXTERN int iemgui_dialog(t_iemgui *iemgui, t_symbol **srl, int argc, t_atom *argv); + +EXTERN int canvas_getdollarzero(void); +EXTERN void canvas_getargs(int *argcp, t_atom **argvp); + +EXTERN void iem_inttosymargs(t_iem_init_symargs *symargp, int n); +EXTERN int iem_symargstoint(t_iem_init_symargs *symargp); +EXTERN void iem_inttofstyle(t_iem_fstyle_flags *fstylep, int n); +EXTERN int iem_fstyletoint(t_iem_fstyle_flags *fstylep); diff --git a/ports/camomile/source/LibPd/pure-data/src/g_array.c b/ports/camomile/source/LibPd/pure-data/src/g_array.c new file mode 100644 index 00000000..7c59893f --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_array.c @@ -0,0 +1,1252 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include +#include +#include /* for read/write to files */ +#include "m_pd.h" +#include "g_canvas.h" +#include + +/* jsarlo { */ +#define ARRAYPAGESIZE 1000 /* this should match the page size in u_main.tk */ +/* } jsarlo */ + +/* --------- "pure" arrays with scalars for elements. --------------- */ + +/* Pure arrays have no a priori graphical capabilities. +They are instantiated by "garrays" below or can be elements of other +scalars (g_scalar.c); their graphical behavior is defined accordingly. */ + +t_array *array_new(t_symbol *templatesym, t_gpointer *parent) +{ + t_array *x = (t_array *)getbytes(sizeof (*x)); + t_template *template; + t_gpointer *gp; + template = template_findbyname(templatesym); + x->a_templatesym = templatesym; + x->a_n = 1; + x->a_elemsize = sizeof(t_word) * template->t_n; + x->a_vec = (char *)getbytes(x->a_elemsize); + /* note here we blithely copy a gpointer instead of "setting" a + new one; this gpointer isn't accounted for and needn't be since + we'll be deleted before the thing pointed to gets deleted anyway; + see array_free. */ + x->a_gp = *parent; + x->a_stub = gstub_new(0, x); + word_init((t_word *)(x->a_vec), template, parent); + return (x); +} + +/* jsarlo { */ +void garray_arrayviewlist_close(t_garray *x); +/* } jsarlo */ + +void array_resize(t_array *x, int n) +{ + int elemsize, oldn; + t_gpointer *gp; + char *tmp; + t_template *template = template_findbyname(x->a_templatesym); + if (n < 1) + n = 1; + oldn = x->a_n; + elemsize = sizeof(t_word) * template->t_n; + + tmp = (char *)resizebytes(x->a_vec, oldn * elemsize, n * elemsize); + if (!tmp) + return; + x->a_vec = tmp; + x->a_n = n; + if (n > oldn) + { + char *cp = x->a_vec + elemsize * oldn; + int i = n - oldn; + for (; i--; cp += elemsize) + { + t_word *wp = (t_word *)cp; + word_init(wp, template, &x->a_gp); + } + } + x->a_valid = ++glist_valid; +} + +void array_resize_and_redraw(t_array *array, t_glist *glist, int n) +{ + t_array *a2 = array; + int vis = glist_isvisible(glist); + while (a2->a_gp.gp_stub->gs_which == GP_ARRAY) + a2 = a2->a_gp.gp_stub->gs_un.gs_array; + if (vis) + gobj_vis(&a2->a_gp.gp_un.gp_scalar->sc_gobj, glist, 0); + array_resize(array, n); + if (vis) + gobj_vis(&a2->a_gp.gp_un.gp_scalar->sc_gobj, glist, 1); +} + +void word_free(t_word *wp, t_template *template); + +void array_free(t_array *x) +{ + int i; + t_template *scalartemplate = template_findbyname(x->a_templatesym); + gstub_cutoff(x->a_stub); + for (i = 0; i < x->a_n; i++) + { + t_word *wp = (t_word *)(x->a_vec + x->a_elemsize * i); + word_free(wp, scalartemplate); + } + freebytes(x->a_vec, x->a_elemsize * x->a_n); + freebytes(x, sizeof *x); +} + +/* --------------------- graphical arrays (garrays) ------------------- */ + +t_class *garray_class; + +struct _garray +{ + t_gobj x_gobj; + t_scalar *x_scalar; /* scalar "containing" the array */ + t_glist *x_glist; /* containing glist */ + t_symbol *x_name; /* unexpanded name (possibly with leading '$') */ + t_symbol *x_realname; /* expanded name (symbol we're bound to) */ + char x_usedindsp; /* true if some DSP routine is using this */ + char x_saveit; /* true if we should save this with parent */ + char x_listviewing; /* true if list view window is open */ + char x_hidename; /* don't print name above graph */ +}; + +static t_pd *garray_arraytemplatecanvas; /* written at setup w/ global lock */ +static const char garray_arraytemplatefile[] = "\ +canvas 0 0 458 153 10;\n\ +#X obj 43 31 struct float-array array z float float style\n\ +float linewidth float color;\n\ +#X obj 43 70 plot z color linewidth 0 0 1 style;\n\ +"; +static const char garray_floattemplatefile[] = "\ +canvas 0 0 458 153 10;\n\ +#X obj 39 26 struct float float y;\n\ +"; + +/* create invisible, built-in canvases to supply templates for floats +and float-arrays. */ + +void garray_init( void) +{ + t_binbuf *b; + b = binbuf_new(); + + glob_setfilename(0, gensym("_float_template"), gensym(".")); + binbuf_text(b, garray_floattemplatefile, strlen(garray_floattemplatefile)); + binbuf_eval(b, &pd_canvasmaker, 0, 0); + vmess(s__X.s_thing, gensym("pop"), "i", 0); + + glob_setfilename(0, gensym("_float_array_template"), gensym(".")); + binbuf_text(b, garray_arraytemplatefile, strlen(garray_arraytemplatefile)); + binbuf_eval(b, &pd_canvasmaker, 0, 0); + garray_arraytemplatecanvas = s__X.s_thing; + vmess(s__X.s_thing, gensym("pop"), "i", 0); + + glob_setfilename(0, &s_, &s_); + binbuf_free(b); +} + +/* create a new scalar attached to a symbol. Used to make floating-point +arrays (the scalar will be of type "float-array"). Currently this is +always called by graph_array() below; but when we make a more general way +to save and create arrays this might get called more directly. */ + +static t_garray *graph_scalar(t_glist *gl, t_symbol *s, t_symbol *templatesym, + int saveit) +{ + int i, zz; + t_garray *x; + t_pd *x2; + t_template *template; + char *str; + t_gpointer gp; + if (!template_findbyname(templatesym)) + return (0); + x = (t_garray *)pd_new(garray_class); + x->x_scalar = scalar_new(gl, templatesym); + x->x_name = s; + x->x_realname = canvas_realizedollar(gl, s); + pd_bind(&x->x_gobj.g_pd, x->x_realname); + x->x_usedindsp = 0; + x->x_saveit = saveit; + x->x_listviewing = 0; + glist_add(gl, &x->x_gobj); + x->x_glist = gl; + return (x); +} + + /* get a garray's "array" structure. */ +t_array *garray_getarray(t_garray *x) +{ + int nwords, zonset, ztype; + t_symbol *zarraytype; + t_scalar *sc = x->x_scalar; + t_symbol *templatesym = sc->sc_template; + t_template *template = template_findbyname(templatesym); + if (!template) + { + error("array: couldn't find template %s", templatesym->s_name); + return (0); + } + if (!template_find_field(template, gensym("z"), + &zonset, &ztype, &zarraytype)) + { + error("array: template %s has no 'z' field", templatesym->s_name); + return (0); + } + if (ztype != DT_ARRAY) + { + error("array: template %s, 'z' field is not an array", + templatesym->s_name); + return (0); + } + return (sc->sc_vec[zonset].w_array); +} + + /* get the "array" structure and furthermore check it's float */ +static t_array *garray_getarray_floatonly(t_garray *x, + int *yonsetp, int *elemsizep) +{ + t_array *a = garray_getarray(x); + int yonset, type; + t_symbol *arraytype; + t_template *template = template_findbyname(a->a_templatesym); + if (!template_find_field(template, gensym("y"), &yonset, + &type, &arraytype) || type != DT_FLOAT) + return (0); + *yonsetp = yonset; + *elemsizep = a->a_elemsize; + return (a); +} + + /* get the array's name. Return nonzero if it should be hidden */ +int garray_getname(t_garray *x, t_symbol **namep) +{ + *namep = x->x_name; + return (x->x_hidename); +} + + /* get a garray's containing glist */ +t_glist *garray_getglist(t_garray *x) +{ + return (x->x_glist); +} + + /* get a garray's associated scalar */ +t_scalar *garray_getscalar(t_garray *x) +{ + return (x->x_scalar); +} + + /* if there is one garray in a graph, reset the graph's coordinates + to fit a new size and style for the garray */ +static void garray_fittograph(t_garray *x, int n, int style) +{ + t_array *array = garray_getarray(x); + t_glist *gl = x->x_glist; + if (gl->gl_list == &x->x_gobj && !x->x_gobj.g_next) + { + vmess(&gl->gl_pd, gensym("bounds"), "ffff", + 0., gl->gl_y1, (double) + (style == PLOTSTYLE_POINTS || n == 1 ? n : n-1), + gl->gl_y2); + + /* hack - if the xlabels seem to want to be from 0 to table size-1, + update the second label */ + if (gl->gl_nxlabels == 2 && !strcmp(gl->gl_xlabel[0]->s_name, "0")) + { + t_atom a; + SETFLOAT(&a, n-1); + gl->gl_xlabel[1] = atom_gensym(&a); + glist_redraw(gl); + } + /* close any dialogs that might have the wrong info now... */ + gfxstub_deleteforkey(gl); + } +} + +/* handle "array" message to glists; call graph_scalar above with +an appropriate template; then set size and flags. This is called +from the menu and in the file format for patches. LATER replace this +by a more coherent (and general) invocation. */ + +t_garray *graph_array(t_glist *gl, t_symbol *s, t_symbol *templateargsym, + t_floatarg fsize, t_floatarg fflags) +{ + int n = fsize, i, zz, nwords, zonset, ztype, saveit; + t_symbol *zarraytype, *asym = gensym("#A"); + t_garray *x; + t_pd *x2; + t_template *template, *ztemplate; + t_symbol *templatesym; + char *str; + int flags = fflags; + t_gpointer gp; + int filestyle = ((flags & 6) >> 1); + int style = (filestyle == 0 ? PLOTSTYLE_POLY : + (filestyle == 1 ? PLOTSTYLE_POINTS : filestyle)); + if (templateargsym != &s_float) + { + error("array %s: only 'float' type understood", templateargsym->s_name); + return (0); + } + templatesym = gensym("pd-float-array"); + template = template_findbyname(templatesym); + if (!template) + { + error("array: couldn't find template %s", templatesym->s_name); + return (0); + } + if (!template_find_field(template, gensym("z"), + &zonset, &ztype, &zarraytype)) + { + error("array: template %s has no 'z' field", templatesym->s_name); + return (0); + } + if (ztype != DT_ARRAY) + { + error("array: template %s, 'z' field is not an array", + templatesym->s_name); + return (0); + } + if (!(ztemplate = template_findbyname(zarraytype))) + { + error("array: no template of type %s", zarraytype->s_name); + return (0); + } + saveit = ((flags & 1) != 0); + x = graph_scalar(gl, s, templatesym, saveit); + x->x_hidename = ((flags & 8) >> 3); + + if (n <= 0) + n = 100; + array_resize(x->x_scalar->sc_vec[zonset].w_array, n); + + template_setfloat(template, gensym("style"), x->x_scalar->sc_vec, + style, 1); + template_setfloat(template, gensym("linewidth"), x->x_scalar->sc_vec, + ((style == PLOTSTYLE_POINTS) ? 2 : 1), 1); + + /* bashily unbind #A -- this would create garbage if #A were + multiply bound but we believe in this context it's at most + bound to whichever textobj or array was created most recently */ + asym->s_thing = 0; + /* and now bind #A to us to receive following messages in the + saved file or copy buffer */ + pd_bind(&x->x_gobj.g_pd, asym); + + garray_redraw(x); + canvas_update_dsp(); + return (x); +} + + /* called from array menu item to create a new one */ +void canvas_menuarray(t_glist *canvas) +{ + t_glist *x = (t_glist *)canvas; + int gcount; + char cmdbuf[200], arraybuf[80]; + for (gcount = 1; gcount < 1000; gcount++) + { + sprintf(arraybuf, "array%d", gcount); + if (!pd_findbyclass(gensym(arraybuf), garray_class)) + break; + } + sprintf(cmdbuf, "pdtk_array_dialog %%s array%d 100 3 1\n", gcount); + gfxstub_new(&x->gl_pd, x, cmdbuf); +} + + /* called from graph_dialog to set properties */ +void garray_properties(t_garray *x) +{ + char cmdbuf[200]; + t_array *a = garray_getarray(x); + t_scalar *sc = x->x_scalar; + int style = template_getfloat(template_findbyname(sc->sc_template), + gensym("style"), x->x_scalar->sc_vec, 1); + int filestyle = (style == 0 ? PLOTSTYLE_POLY : + (style == 1 ? PLOTSTYLE_POINTS : style)); + + if (!a) + return; + gfxstub_deleteforkey(x); + /* create dialog window. LATER fix this to escape '$' + properly; right now we just detect a leading '$' and escape + it. There should be a systematic way of doing this. */ + sprintf(cmdbuf, "pdtk_array_dialog %%s %s %d %d 0\n", + iemgui_dollar2raute(x->x_name)->s_name, a->a_n, x->x_saveit + + 2 * filestyle); + gfxstub_new(&x->x_gobj.g_pd, x, cmdbuf); +} + + /* this is called back from the dialog window to create a garray. + The otherflag requests that we find an existing graph to put it in. */ +void glist_arraydialog(t_glist *parent, t_symbol *name, t_floatarg size, + t_floatarg fflags, t_floatarg otherflag) +{ + t_glist *gl; + t_garray *a; + int flags = fflags; + if (size < 1) + size = 1; + if (otherflag == 0 || (!(gl = glist_findgraph(parent)))) + gl = glist_addglist(parent, &s_, 0, 1, + size, -1, 0, 0, 0, 0); + a = graph_array(gl, iemgui_raute2dollar(name), &s_float, size, flags); + canvas_dirty(parent, 1); +} + + /* this is called from the properties dialog window for an existing array */ +void garray_arraydialog(t_garray *x, t_symbol *name, t_floatarg fsize, + t_floatarg fflags, t_floatarg deleteit) +{ + int flags = fflags; + int saveit = ((flags & 1) != 0); + int filestyle = ((flags & 6) >> 1); + int style = (filestyle == 0 ? PLOTSTYLE_POLY : + (filestyle == 1 ? PLOTSTYLE_POINTS : filestyle)); + t_float stylewas = template_getfloat( + template_findbyname(x->x_scalar->sc_template), + gensym("style"), x->x_scalar->sc_vec, 1); + if (deleteit != 0) + { + int wasused = x->x_usedindsp; + glist_delete(x->x_glist, &x->x_gobj); + if (wasused) + canvas_update_dsp(); + } + else + { + long size; + int styleonset, styletype; + t_symbol *stylearraytype; + t_symbol *argname = iemgui_raute2dollar(name); + t_array *a = garray_getarray(x); + t_template *scalartemplate; + if (!a) + { + pd_error(x, "can't find array\n"); + return; + } + if (!(scalartemplate = template_findbyname(x->x_scalar->sc_template))) + { + error("array: no template of type %s", + x->x_scalar->sc_template->s_name); + return; + } + if (argname != x->x_name) + { + /* jsarlo { */ + if (x->x_listviewing) + { + garray_arrayviewlist_close(x); + } + /* } jsarlo */ + x->x_name = argname; + pd_unbind(&x->x_gobj.g_pd, x->x_realname); + x->x_realname = canvas_realizedollar(x->x_glist, argname); + pd_bind(&x->x_gobj.g_pd, x->x_realname); + /* redraw the whole glist, just so the name change shows up */ + if (x->x_glist->gl_havewindow) + canvas_redraw(x->x_glist); + else if (glist_isvisible(x->x_glist->gl_owner)) + { + gobj_vis(&x->x_glist->gl_gobj, x->x_glist->gl_owner, 0); + gobj_vis(&x->x_glist->gl_gobj, x->x_glist->gl_owner, 1); + } + canvas_update_dsp(); + } + size = fsize; + if (size < 1) + size = 1; + if (size != a->a_n) + garray_resize_long(x, size); + else if (style != stylewas) + garray_fittograph(x, (int)size, style); + template_setfloat(scalartemplate, gensym("style"), + x->x_scalar->sc_vec, (t_float)style, 0); + + garray_setsaveit(x, (saveit != 0)); + garray_redraw(x); + canvas_dirty(x->x_glist, 1); + } +} + +/* jsarlo { */ +void garray_arrayviewlist_new(t_garray *x) +{ + int i, xonset=0, yonset=0, type=0, elemsize=0; + t_float yval; + char cmdbuf[200]; + t_symbol *arraytype; + t_array *a = garray_getarray_floatonly(x, &yonset, &elemsize); + + if (!a) + { + /* FIXME */ + error("error in garray_arrayviewlist_new()"); + } + x->x_listviewing = 1; + sprintf(cmdbuf, + "pdtk_array_listview_new %%s %s %d\n", + x->x_realname->s_name, + 0); + gfxstub_new(&x->x_gobj.g_pd, x, cmdbuf); + for (i = 0; i < ARRAYPAGESIZE && i < a->a_n; i++) + { + yval = *(t_float *)(a->a_vec + + elemsize * i + yonset); + sys_vgui(".%sArrayWindow.lb insert %d {%d) %g}\n", + x->x_realname->s_name, + i, + i, + yval); + } +} + +void garray_arrayviewlist_fillpage(t_garray *x, + t_float page, + t_float fTopItem) +{ + int i, xonset=0, yonset=0, type=0, elemsize=0, topItem; + t_float yval; + char cmdbuf[200]; + t_symbol *arraytype; + t_array *a = garray_getarray_floatonly(x, &yonset, &elemsize); + + topItem = (int)fTopItem; + if (!a) + { + /* FIXME */ + error("error in garray_arrayviewlist_new()"); + } + + if (page < 0) { + page = 0; + sys_vgui("pdtk_array_listview_setpage %s %d\n", + x->x_realname->s_name, + (int)page); + } + else if ((page * ARRAYPAGESIZE) >= a->a_n) { + page = (int)(((int)a->a_n - 1)/ (int)ARRAYPAGESIZE); + sys_vgui("pdtk_array_listview_setpage %s %d\n", + x->x_realname->s_name, + (int)page); + } + sys_vgui(".%sArrayWindow.lb delete 0 %d\n", + x->x_realname->s_name, + ARRAYPAGESIZE - 1); + for (i = page * ARRAYPAGESIZE; + (i < (page + 1) * ARRAYPAGESIZE && i < a->a_n); + i++) + { + yval = *(t_float *)(a->a_vec + \ + elemsize * i + yonset); + sys_vgui(".%sArrayWindow.lb insert %d {%d) %g}\n", + x->x_realname->s_name, + i % ARRAYPAGESIZE, + i, + yval); + } + sys_vgui(".%sArrayWindow.lb yview %d\n", + x->x_realname->s_name, + topItem); +} + +void garray_arrayviewlist_close(t_garray *x) +{ + x->x_listviewing = 0; + sys_vgui("pdtk_array_listview_closeWindow %s\n", + x->x_realname->s_name); +} +/* } jsarlo */ + +static void garray_free(t_garray *x) +{ + t_pd *x2; + sys_unqueuegui(&x->x_gobj); + /* jsarlo { */ + if (x->x_listviewing) + { + garray_arrayviewlist_close(x); + } + /* } jsarlo */ + gfxstub_deleteforkey(x); + pd_unbind(&x->x_gobj.g_pd, x->x_realname); + /* just in case we're still bound to #A from loading... */ + while ((x2 = pd_findbyclass(gensym("#A"), garray_class))) + pd_unbind(x2, gensym("#A")); + pd_free(&x->x_scalar->sc_gobj.g_pd); +} + +/* ------------- code used by both array and plot widget functions ---- */ + +void array_redraw(t_array *a, t_glist *glist) +{ + while (a->a_gp.gp_stub->gs_which == GP_ARRAY) + a = a->a_gp.gp_stub->gs_un.gs_array; + scalar_redraw(a->a_gp.gp_un.gp_scalar, glist); +} + + /* routine to get screen coordinates of a point in an array */ +void array_getcoordinate(t_glist *glist, + char *elem, int xonset, int yonset, int wonset, int indx, + t_float basex, t_float basey, t_float xinc, + t_fielddesc *xfielddesc, t_fielddesc *yfielddesc, t_fielddesc *wfielddesc, + t_float *xp, t_float *yp, t_float *wp) +{ + t_float xval, yval, ypix, wpix; + if (xonset >= 0) + xval = *(t_float *)(elem + xonset); + else xval = indx * xinc; + if (yonset >= 0) + yval = *(t_float *)(elem + yonset); + else yval = 0; + ypix = glist_ytopixels(glist, basey + + fielddesc_cvttocoord(yfielddesc, yval)); + if (wonset >= 0) + { + /* found "w" field which controls linewidth. */ + t_float wval = *(t_float *)(elem + wonset); + wpix = glist_ytopixels(glist, basey + + fielddesc_cvttocoord(yfielddesc, yval) + + fielddesc_cvttocoord(wfielddesc, wval)) - ypix; + if (wpix < 0) + wpix = -wpix; + } + else wpix = 1; + *xp = glist_xtopixels(glist, basex + + fielddesc_cvttocoord(xfielddesc, xval)); + *yp = ypix; + *wp = wpix; +} + +static void array_getrect(t_array *array, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_float x1 = 0x7fffffff, y1 = 0x7fffffff, x2 = -0x7fffffff, y2 = -0x7fffffff; + t_canvas *elemtemplatecanvas; + t_template *elemtemplate; + int elemsize, yonset, wonset, xonset, i; + + if (!array_getfields(array->a_templatesym, &elemtemplatecanvas, + &elemtemplate, &elemsize, 0, 0, 0, &xonset, &yonset, &wonset)) + { + int incr; + /* if it has more than 2000 points, just check 300 of them. */ + if (array->a_n < 2000) + incr = 1; + else incr = array->a_n / 300; + for (i = 0; i < array->a_n; i += incr) + { + t_float pxpix, pypix, pwpix, dx, dy; + array_getcoordinate(glist, (char *)(array->a_vec) + + i * elemsize, + xonset, yonset, wonset, i, 0, 0, 1, + 0, 0, 0, + &pxpix, &pypix, &pwpix); + if (pwpix < 2) + pwpix = 2; + if (pxpix < x1) + x1 = pxpix; + if (pxpix > x2) + x2 = pxpix; + if (pypix - pwpix < y1) + y1 = pypix - pwpix; + if (pypix + pwpix > y2) + y2 = pypix + pwpix; + } + } + *xp1 = x1; + *yp1 = y1; + *xp2 = x2; + *yp2 = y2; +} + +/* -------------------- widget behavior for garray ------------ */ + +static void garray_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_garray *x = (t_garray *)z; + gobj_getrect(&x->x_scalar->sc_gobj, glist, xp1, yp1, xp2, yp2); +} + +static void garray_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + /* refuse */ +} + +static void garray_select(t_gobj *z, t_glist *glist, int state) +{ + t_garray *x = (t_garray *)z; + /* fill in later */ +} + +static void garray_activate(t_gobj *z, t_glist *glist, int state) +{ +} + +static void garray_delete(t_gobj *z, t_glist *glist) +{ + /* nothing to do */ +} + +static void garray_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_garray *x = (t_garray *)z; + gobj_vis(&x->x_scalar->sc_gobj, glist, vis); +} + +static int garray_click(t_gobj *z, t_glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_garray *x = (t_garray *)z; + return (gobj_click(&x->x_scalar->sc_gobj, glist, + xpix, ypix, shift, alt, dbl, doit)); +} + +#define ARRAYWRITECHUNKSIZE 1000 + +void garray_savecontentsto(t_garray *x, t_binbuf *b) +{ + if (x->x_saveit) + { + t_array *array = garray_getarray(x); + int n = array->a_n, n2 = 0; + if (n > 200000) + post("warning: I'm saving an array with %d points!\n", n); + while (n2 < n) + { + int chunk = n - n2, i; + if (chunk > ARRAYWRITECHUNKSIZE) + chunk = ARRAYWRITECHUNKSIZE; + binbuf_addv(b, "si", gensym("#A"), n2); + for (i = 0; i < chunk; i++) + binbuf_addv(b, "f", ((t_word *)(array->a_vec))[n2+i].w_float); + binbuf_addv(b, ";"); + n2 += chunk; + } + } +} + +static void garray_save(t_gobj *z, t_binbuf *b) +{ + int style, filestyle; + t_garray *x = (t_garray *)z; + t_array *array = garray_getarray(x); + t_template *scalartemplate; + if (x->x_scalar->sc_template != gensym("pd-float-array")) + { + /* LATER "save" the scalar as such */ + pd_error(x, "can't save arrays of type %s yet", + x->x_scalar->sc_template->s_name); + return; + } + if (!(scalartemplate = template_findbyname(x->x_scalar->sc_template))) + { + error("array: no template of type %s", + x->x_scalar->sc_template->s_name); + return; + } + style = template_getfloat(scalartemplate, gensym("style"), + x->x_scalar->sc_vec, 0); + filestyle = (style == PLOTSTYLE_POINTS ? 1 : + (style == PLOTSTYLE_POLY ? 0 : style)); + binbuf_addv(b, "sssisi;", gensym("#X"), gensym("array"), + x->x_name, array->a_n, &s_float, + x->x_saveit + 2 * filestyle + 8*x->x_hidename); + garray_savecontentsto(x, b); +} + +const t_widgetbehavior garray_widgetbehavior = +{ + garray_getrect, + garray_displace, + garray_select, + garray_activate, + garray_delete, + garray_vis, + garray_click, +}; + +/* ----------------------- public functions -------------------- */ + +void garray_usedindsp(t_garray *x) +{ + x->x_usedindsp = 1; +} + +static void garray_doredraw(t_gobj *client, t_glist *glist) +{ + t_garray *x = (t_garray *)client; + if (glist_isvisible(x->x_glist) && gobj_shouldvis(client, glist)) + { + garray_vis(&x->x_gobj, x->x_glist, 0); + garray_vis(&x->x_gobj, x->x_glist, 1); + } +} + +void garray_redraw(t_garray *x) +{ + if (glist_isvisible(x->x_glist)) + sys_queuegui(&x->x_gobj, x->x_glist, garray_doredraw); + /* jsarlo { */ + /* this happens in garray_vis() when array is visible for + performance reasons */ + else + { + if (x->x_listviewing) + sys_vgui("pdtk_array_listview_fillpage %s\n", + x->x_realname->s_name); + } + /* } jsarlo */ +} + + /* This functiopn gets the template of an array; if we can't figure + out what template an array's elements belong to we're in grave trouble + when it's time to free or resize it. */ +t_template *garray_template(t_garray *x) +{ + t_array *array = garray_getarray(x); + t_template *template = + (array ? template_findbyname(array->a_templatesym) : 0); + if (!template) + bug("garray_template"); + return (template); +} + +int garray_npoints(t_garray *x) /* get the length */ +{ + t_array *array = garray_getarray(x); + return (array->a_n); +} + +char *garray_vec(t_garray *x) /* get the contents */ +{ + t_array *array = garray_getarray(x); + return ((char *)(array->a_vec)); +} + + /* routine that checks if we're just an array of floats and if + so returns the goods */ + +int garray_getfloatwords(t_garray *x, int *size, t_word **vec) +{ + int yonset, type, elemsize; + t_array *a = garray_getarray_floatonly(x, &yonset, &elemsize); + if (!a) + { + error("%s: needs floating-point 'y' field", x->x_realname->s_name); + return (0); + } + else if (elemsize != sizeof(t_word)) + { + error("%s: has more than one field", x->x_realname->s_name); + return (0); + } + *size = garray_npoints(x); + *vec = (t_word *)garray_vec(x); + return (1); +} + /* older, non-64-bit safe version, supplied for older externs */ + +int garray_getfloatarray(t_garray *x, int *size, t_float **vec) +{ + if (sizeof(t_word) != sizeof(t_float)) + { + t_symbol *patchname; + if (x->x_glist->gl_owner) + patchname = x->x_glist->gl_owner->gl_name; + else + patchname = x->x_glist->gl_name; + error("An operation on the array '%s' in the patch '%s'", + x->x_name->s_name, patchname->s_name); + error("failed since it uses garray_getfloatarray while running 64-bit!"); + } + return (garray_getfloatwords(x, size, (t_word **)vec)); +} + + /* set the "saveit" flag */ +void garray_setsaveit(t_garray *x, int saveit) +{ + if (x->x_saveit && !saveit) + post("warning: array %s: clearing save-in-patch flag", + x->x_name->s_name); + x->x_saveit = saveit; +} + +/*------------------- Pd messages ------------------------ */ +static void garray_const(t_garray *x, t_floatarg g) +{ + int yonset, i, elemsize; + t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize); + if (!array) + error("%s: needs floating-point 'y' field", x->x_realname->s_name); + else for (i = 0; i < array->a_n; i++) + *((t_float *)((char *)array->a_vec + + elemsize * i) + yonset) = g; + garray_redraw(x); +} + + /* sum of Fourier components; called from routines below */ +static void garray_dofo(t_garray *x, long npoints, t_float dcval, + int nsin, t_float *vsin, int sineflag) +{ + double phase, phaseincr, fj; + int yonset, i, j, elemsize; + t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize); + if (!array) + { + error("%s: needs floating-point 'y' field", x->x_realname->s_name); + return; + } + if (npoints == 0) + npoints = 512; /* dunno what a good default would be... */ + if (npoints != (1 << ilog2((int)npoints))) + post("%s: rounnding to %d points", array->a_templatesym->s_name, + (npoints = (1<a_n; i++, phase += phaseincr) + { + double sum = dcval; + if (sineflag) + for (j = 0, fj = phase; j < nsin; j++, fj += phase) + sum += vsin[j] * sin(fj); + else + for (j = 0, fj = 0; j < nsin; j++, fj += phase) + sum += vsin[j] * cos(fj); + *((t_float *)((array->a_vec + elemsize * i)) + yonset) + = sum; + } + garray_redraw(x); +} + +static void garray_sinesum(t_garray *x, t_symbol *s, int argc, t_atom *argv) +{ + t_float *svec; + long npoints; + int i; + if (argc < 2) + { + error("sinesum: %s: need number of points and partial strengths", + x->x_realname->s_name); + return; + } + + npoints = atom_getfloatarg(0, argc, argv); + argv++, argc--; + + svec = (t_float *)t_getbytes(sizeof(t_float) * argc); + if (!svec) return; + + for (i = 0; i < argc; i++) + svec[i] = atom_getfloatarg(i, argc, argv); + garray_dofo(x, npoints, 0, argc, svec, 1); + t_freebytes(svec, sizeof(t_float) * argc); +} + +static void garray_cosinesum(t_garray *x, t_symbol *s, int argc, t_atom *argv) +{ + t_float *svec; + long npoints; + int i; + if (argc < 2) + { + error("sinesum: %s: need number of points and partial strengths", + x->x_realname->s_name); + return; + } + + npoints = atom_getfloatarg(0, argc, argv); + argv++, argc--; + + svec = (t_float *)t_getbytes(sizeof(t_float) * argc); + if (!svec) return; + + for (i = 0; i < argc; i++) + svec[i] = atom_getfloatarg(i, argc, argv); + garray_dofo(x, npoints, 0, argc, svec, 0); + t_freebytes(svec, sizeof(t_float) * argc); +} + +static void garray_normalize(t_garray *x, t_float f) +{ + int type, i; + double maxv, renormer; + int yonset, elemsize; + t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize); + if (!array) + { + error("%s: needs floating-point 'y' field", x->x_realname->s_name); + return; + } + + if (f <= 0) + f = 1; + + for (i = 0, maxv = 0; i < array->a_n; i++) + { + double v = *((t_float *)(array->a_vec + elemsize * i) + + yonset); + if (v > maxv) + maxv = v; + if (-v > maxv) + maxv = -v; + } + if (maxv > 0) + { + renormer = f / maxv; + for (i = 0; i < array->a_n; i++) + *((t_float *)(array->a_vec + elemsize * i) + yonset) + *= renormer; + } + garray_redraw(x); +} + + /* list -- the first value is an index; subsequent values are put in + the "y" slot of the array. This generalizes Max's "table", sort of. */ +static void garray_list(t_garray *x, t_symbol *s, int argc, t_atom *argv) +{ + int i; + int yonset, elemsize; + t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize); + if (!array) + { + error("%s: needs floating-point 'y' field", x->x_realname->s_name); + return; + } + if (argc < 2) return; + else + { + int firstindex = atom_getfloat(argv); + argc--; + argv++; + /* drop negative x values */ + if (firstindex < 0) + { + argc += firstindex; + argv -= firstindex; + firstindex = 0; + if (argc <= 0) return; + } + if (argc + firstindex > array->a_n) + { + argc = array->a_n - firstindex; + if (argc <= 0) return; + } + for (i = 0; i < argc; i++) + *((t_float *)(array->a_vec + elemsize * (i + firstindex)) + yonset) + = atom_getfloat(argv + i); + } + garray_redraw(x); +} + + /* forward a "bounds" message to the owning graph */ +static void garray_bounds(t_garray *x, t_floatarg x1, t_floatarg y1, + t_floatarg x2, t_floatarg y2) +{ + vmess(&x->x_glist->gl_pd, gensym("bounds"), "ffff", x1, y1, x2, y2); +} + + /* same for "xticks", etc */ +static void garray_xticks(t_garray *x, + t_floatarg point, t_floatarg inc, t_floatarg f) +{ + vmess(&x->x_glist->gl_pd, gensym("xticks"), "fff", point, inc, f); +} + +static void garray_yticks(t_garray *x, + t_floatarg point, t_floatarg inc, t_floatarg f) +{ + vmess(&x->x_glist->gl_pd, gensym("yticks"), "fff", point, inc, f); +} + +static void garray_xlabel(t_garray *x, t_symbol *s, int argc, t_atom *argv) +{ + typedmess(&x->x_glist->gl_pd, s, argc, argv); +} + +static void garray_ylabel(t_garray *x, t_symbol *s, int argc, t_atom *argv) +{ + typedmess(&x->x_glist->gl_pd, s, argc, argv); +} + /* change the name of a garray. */ +static void garray_rename(t_garray *x, t_symbol *s) +{ + /* jsarlo { */ + if (x->x_listviewing) + { + garray_arrayviewlist_close(x); + } + /* } jsarlo */ + pd_unbind(&x->x_gobj.g_pd, x->x_realname); + pd_bind(&x->x_gobj.g_pd, x->x_realname = x->x_name = s); + garray_redraw(x); +} + +static void garray_read(t_garray *x, t_symbol *filename) +{ + int nelem, filedesc, i; + FILE *fd; + char buf[MAXPDSTRING], *bufptr; + int yonset, elemsize; + t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize); + if (!array) + { + error("%s: needs floating-point 'y' field", x->x_realname->s_name); + return; + } + nelem = array->a_n; + if ((filedesc = canvas_open(glist_getcanvas(x->x_glist), + filename->s_name, "", buf, &bufptr, MAXPDSTRING, 0)) < 0 + || !(fd = fdopen(filedesc, "r"))) + { + error("%s: can't open", filename->s_name); + return; + } + for (i = 0; i < nelem; i++) + { + double f; + if (!fscanf(fd, "%lf", &f)) + { + post("%s: read %d elements into table of size %d", + filename->s_name, i, nelem); + break; + } + else *((t_float *)(array->a_vec + elemsize * i) + yonset) = f; + } + while (i < nelem) + *((t_float *)(array->a_vec + + elemsize * i) + yonset) = 0, i++; + fclose(fd); + garray_redraw(x); +} + +static void garray_write(t_garray *x, t_symbol *filename) +{ + FILE *fd; + char buf[MAXPDSTRING]; + int yonset, elemsize, i; + t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize); + if (!array) + { + error("%s: needs floating-point 'y' field", x->x_realname->s_name); + return; + } + canvas_makefilename(glist_getcanvas(x->x_glist), filename->s_name, + buf, MAXPDSTRING); + if (!(fd = sys_fopen(buf, "w"))) + { + error("%s: can't create", buf); + return; + } + for (i = 0; i < array->a_n; i++) + { + if (fprintf(fd, "%g\n", + *(t_float *)(((array->a_vec + sizeof(t_word) * i)) + yonset)) < 1) + { + post("%s: write error", filename->s_name); + break; + } + } + fclose(fd); +} + + + /* this should be renamed and moved... */ +int garray_ambigendian(void) +{ + unsigned short s = 1; + unsigned char c = *(char *)(&s); + return (c==0); +} + +void garray_resize_long(t_garray *x, long n) +{ + t_array *array = garray_getarray(x); + t_glist *gl = x->x_glist; + if (n < 1) + n = 1; + garray_fittograph(x, (int)n, template_getfloat( + template_findbyname(x->x_scalar->sc_template), + gensym("style"), x->x_scalar->sc_vec, 1)); + array_resize_and_redraw(array, x->x_glist, (int)n); + if (x->x_usedindsp) + canvas_update_dsp(); +} + + /* float version to use as Pd method */ +void garray_resize(t_garray *x, t_floatarg f) +{ + garray_resize_long(x, f); +} + +/* ignore zoom for now */ +static void garray_zoom(t_garray *x, t_floatarg f) +{ +} + +static void garray_print(t_garray *x) +{ + t_array *array = garray_getarray(x); + post("garray %s: template %s, length %d", + x->x_realname->s_name, array->a_templatesym->s_name, array->a_n); +} + +void g_array_setup(void) +{ + garray_class = class_new(gensym("array"), 0, (t_method)garray_free, + sizeof(t_garray), CLASS_GOBJ, 0); + class_setwidget(garray_class, &garray_widgetbehavior); + class_addmethod(garray_class, (t_method)garray_const, gensym("const"), + A_DEFFLOAT, A_NULL); + class_addlist(garray_class, garray_list); + class_addmethod(garray_class, (t_method)garray_bounds, gensym("bounds"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(garray_class, (t_method)garray_xticks, gensym("xticks"), + A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(garray_class, (t_method)garray_xlabel, gensym("xlabel"), + A_GIMME, 0); + class_addmethod(garray_class, (t_method)garray_yticks, gensym("yticks"), + A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(garray_class, (t_method)garray_ylabel, gensym("ylabel"), + A_GIMME, 0); + class_addmethod(garray_class, (t_method)garray_rename, gensym("rename"), + A_SYMBOL, 0); + class_addmethod(garray_class, (t_method)garray_read, gensym("read"), + A_SYMBOL, A_NULL); + class_addmethod(garray_class, (t_method)garray_write, gensym("write"), + A_SYMBOL, A_NULL); + class_addmethod(garray_class, (t_method)garray_resize, gensym("resize"), + A_FLOAT, A_NULL); + class_addmethod(garray_class, (t_method)garray_zoom, gensym("zoom"), + A_FLOAT, 0); + class_addmethod(garray_class, (t_method)garray_print, gensym("print"), + A_NULL); + class_addmethod(garray_class, (t_method)garray_sinesum, gensym("sinesum"), + A_GIMME, 0); + class_addmethod(garray_class, (t_method)garray_cosinesum, + gensym("cosinesum"), A_GIMME, 0); + class_addmethod(garray_class, (t_method)garray_normalize, + gensym("normalize"), A_DEFFLOAT, 0); + class_addmethod(garray_class, (t_method)garray_arraydialog, + gensym("arraydialog"), A_SYMBOL, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); +/* jsarlo { */ + class_addmethod(garray_class, (t_method)garray_arrayviewlist_new, + gensym("arrayviewlistnew"), A_NULL); + class_addmethod(garray_class, (t_method)garray_arrayviewlist_fillpage, + gensym("arrayviewlistfillpage"), A_FLOAT, A_DEFFLOAT, A_NULL); + class_addmethod(garray_class, (t_method)garray_arrayviewlist_close, + gensym("arrayviewclose"), A_NULL); +/* } jsarlo */ + class_setsavefn(garray_class, garray_save); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_bang.c b/ports/camomile/source/LibPd/pure-data/src/g_bang.c new file mode 100644 index 00000000..2d0acbe7 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_bang.c @@ -0,0 +1,578 @@ +/* Copyright (c) 1997-1999 Miller Puckette. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */ +/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */ + +#include +#include +#include +#include +#include "m_pd.h" +#include "g_canvas.h" + +#include "g_all_guis.h" +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +/* --------------- bng gui-bang ------------------------- */ + +t_widgetbehavior bng_widgetbehavior; +static t_class *bng_class; + +/* widget helper functions */ + +void bng_draw_update(t_bng *x, t_glist *glist) +{ + if(glist_isvisible(glist)) + { + sys_vgui(".x%lx.c itemconfigure %lxBUT -fill #%6.6x\n", + glist_getcanvas(glist), x, + (x->x_flashed ? x->x_gui.x_fcol : x->x_gui.x_bcol)); + } +} + +void bng_draw_new(t_bng *x, t_glist *glist) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + int inset = IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -fill #%6.6x -tags %lxBASE\n", + canvas, xpos, ypos, + xpos + x->x_gui.x_w, ypos + x->x_gui.x_h, + IEMGUI_ZOOM(x), + x->x_gui.x_bcol, x); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n", + canvas, + xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh, + xpos + iow, ypos + x->x_gui.x_h, + x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n", + canvas, + xpos, ypos, + xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh, + x, 0); + sys_vgui(".x%lx.c create oval %d %d %d %d -width %d -fill #%6.6x -tags %lxBUT\n", + canvas, xpos + inset, ypos + inset, + xpos + x->x_gui.x_w - inset, ypos + x->x_gui.x_h - inset, + IEMGUI_ZOOM(x), + (x->x_flashed ? x->x_gui.x_fcol : x->x_gui.x_bcol), x); + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \ + -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n", + canvas, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x), + (strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""), + x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + x->x_gui.x_lcol, x); +} + +void bng_draw_move(t_bng *x, t_glist *glist) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + int inset = IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n", + canvas, x, xpos, ypos, + xpos + x->x_gui.x_w, ypos + x->x_gui.x_h); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n", + canvas, x, 0, + xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh, + xpos + iow, ypos + x->x_gui.x_h); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n", + canvas, x, 0, + xpos, ypos, + xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh); + sys_vgui(".x%lx.c coords %lxBUT %d %d %d %d\n", + canvas, x, xpos + inset, ypos + inset, + xpos + x->x_gui.x_w - inset, ypos + x->x_gui.x_h - inset); + sys_vgui(".x%lx.c itemconfigure %lxBUT -fill #%6.6x\n", canvas, x, + (x->x_flashed ? x->x_gui.x_fcol : x->x_gui.x_bcol)); + sys_vgui(".x%lx.c coords %lxLABEL %d %d\n", + canvas, x, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x)); +} + +void bng_draw_erase(t_bng* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c delete %lxBASE\n", canvas, x); + sys_vgui(".x%lx.c delete %lxBUT\n", canvas, x); + sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); +} + +void bng_draw_config(t_bng* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%6.6x -text {%s} \n", + canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + (x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol), + (strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : "")); + sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%6.6x\n", canvas, x, x->x_gui.x_bcol); + sys_vgui(".x%lx.c itemconfigure %lxBUT -fill #%6.6x\n", canvas, x, + (x->x_flashed ? x->x_gui.x_fcol : x->x_gui.x_bcol)); +} + +void bng_draw_io(t_bng* x, t_glist* glist, int old_snd_rcv_flags) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able) { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n", + canvas, + xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh, + xpos + iow, ypos + x->x_gui.x_h, + x, 0); + /* keep above outlet */ + sys_vgui(".x%lx.c raise %lxLABEL %lxOUT%d\n", canvas, x, x, 0); + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able) { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n", + canvas, + xpos, ypos, + xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh, + x, 0); + /* keep above inlet */ + sys_vgui(".x%lx.c raise %lxLABEL %lxIN%d\n", canvas, x, x, 0); + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); +} + +void bng_draw_select(t_bng* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + if(x->x_gui.x_fsf.x_selected) + { + sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + sys_vgui(".x%lx.c itemconfigure %lxBUT -outline #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + } + else + { + sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%6.6x\n", canvas, x, IEM_GUI_COLOR_NORMAL); + sys_vgui(".x%lx.c itemconfigure %lxBUT -outline #%6.6x\n", canvas, x, IEM_GUI_COLOR_NORMAL); + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%6.6x\n", canvas, x, x->x_gui.x_lcol); + } +} + +void bng_draw(t_bng *x, t_glist *glist, int mode) +{ + if(mode == IEM_GUI_DRAW_MODE_UPDATE) + bng_draw_update(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_MOVE) + bng_draw_move(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_NEW) + bng_draw_new(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_SELECT) + bng_draw_select(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_ERASE) + bng_draw_erase(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_CONFIG) + bng_draw_config(x, glist); + else if(mode >= IEM_GUI_DRAW_MODE_IO) + bng_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO); +} + +/* ------------------------ bng widgetbehaviour----------------------------- */ + +static void bng_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_bng *x = (t_bng *)z; + + *xp1 = text_xpix(&x->x_gui.x_obj, glist); + *yp1 = text_ypix(&x->x_gui.x_obj, glist); + *xp2 = *xp1 + x->x_gui.x_w; + *yp2 = *yp1 + x->x_gui.x_h; +} + +static void bng_save(t_gobj *z, t_binbuf *b) +{ + t_bng *x = (t_bng *)z; + t_symbol *bflcol[3]; + t_symbol *srl[3]; + + iemgui_save(&x->x_gui, srl, bflcol); + binbuf_addv(b, "ssiisiiiisssiiiisss", gensym("#X"),gensym("obj"), + (int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix, + gensym("bng"), x->x_gui.x_w/IEMGUI_ZOOM(x), + x->x_flashtime_hold, x->x_flashtime_break, + iem_symargstoint(&x->x_gui.x_isa), + srl[0], srl[1], srl[2], + x->x_gui.x_ldx, x->x_gui.x_ldy, + iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize, + bflcol[0], bflcol[1], bflcol[2]); + binbuf_addv(b, ";"); +} + +void bng_check_minmax(t_bng *x, int ftbreak, int fthold) +{ + if(ftbreak > fthold) + { + int h; + + h = ftbreak; + ftbreak = fthold; + fthold = h; + } + if(ftbreak < IEM_BNG_MINBREAKFLASHTIME) + ftbreak = IEM_BNG_MINBREAKFLASHTIME; + if(fthold < IEM_BNG_MINHOLDFLASHTIME) + fthold = IEM_BNG_MINHOLDFLASHTIME; + x->x_flashtime_break = ftbreak; + x->x_flashtime_hold = fthold; +} + +static void bng_properties(t_gobj *z, t_glist *owner) +{ + t_bng *x = (t_bng *)z; + char buf[800]; + t_symbol *srl[3]; + + iemgui_properties(&x->x_gui, srl); + sprintf(buf, "pdtk_iemgui_dialog %%s |bang| \ + ----------dimensions(pix):----------- %d %d size: 0 0 empty \ + --------flash-time(ms)(ms):--------- %d intrrpt: %d hold: %d \ + %d empty empty %d %d empty %d \ + %s %s \ + %s %d %d \ + %d %d \ + #%06x #%06x #%06x\n", + x->x_gui.x_w/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE, + x->x_flashtime_break, x->x_flashtime_hold, 2,/*min_max_schedule+clip*/ + -1, x->x_gui.x_isa.x_loadinit, -1, -1,/*no linlog, no multi*/ + srl[0]->s_name, srl[1]->s_name, + srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy, + x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize, + 0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol); + gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf); +} + +static void bng_set(t_bng *x) +{ + int holdtime = x->x_flashtime_hold; + int sincelast = clock_gettimesince(x->x_lastflashtime); + x->x_lastflashtime = clock_getsystime(); + if (sincelast < x->x_flashtime_hold*2) + holdtime = sincelast/2; + if (holdtime < x->x_flashtime_break) + holdtime = x->x_flashtime_break; + x->x_flashed = 1; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + clock_delay(x->x_clock_hld, holdtime); +} + +static void bng_bout1(t_bng *x) /*wird nur mehr gesendet, wenn snd != rcv*/ +{ + if(!x->x_gui.x_fsf.x_put_in2out) + { + x->x_gui.x_isa.x_locked = 1; + clock_delay(x->x_clock_lck, 2); + } + outlet_bang(x->x_gui.x_obj.ob_outlet); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing && x->x_gui.x_fsf.x_put_in2out) + pd_bang(x->x_gui.x_snd->s_thing); +} + +static void bng_bout2(t_bng *x) /*wird immer gesendet, wenn moeglich*/ +{ + if(!x->x_gui.x_fsf.x_put_in2out) + { + x->x_gui.x_isa.x_locked = 1; + clock_delay(x->x_clock_lck, 2); + } + outlet_bang(x->x_gui.x_obj.ob_outlet); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_bang(x->x_gui.x_snd->s_thing); +} + +static void bng_bang(t_bng *x) /*wird nur mehr gesendet, wenn snd != rcv*/ +{ + if(!x->x_gui.x_isa.x_locked) + { + bng_set(x); + bng_bout1(x); + } +} + +static void bng_bang2(t_bng *x) /*wird immer gesendet, wenn moeglich*/ +{ + if(!x->x_gui.x_isa.x_locked) + { + bng_set(x); + bng_bout2(x); + } +} + +static void bng_dialog(t_bng *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *srl[3]; + int a = (int)atom_getfloatarg(0, argc, argv); + int fthold = (int)atom_getfloatarg(2, argc, argv); + int ftbreak = (int)atom_getfloatarg(3, argc, argv); + int sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv); + + x->x_gui.x_w = iemgui_clip_size(a) * IEMGUI_ZOOM(x); + x->x_gui.x_h = x->x_gui.x_w; + bng_check_minmax(x, ftbreak, fthold); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x); +} + +static void bng_click(t_bng *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + bng_set(x); + bng_bout2(x); +} + +static int bng_newclick(t_gobj *z, struct _glist *glist, int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + if(doit) + bng_click((t_bng *)z, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, 0, (t_floatarg)alt); + return (1); +} + +static void bng_float(t_bng *x, t_floatarg f) +{bng_bang2(x);} + +static void bng_symbol(t_bng *x, t_symbol *s) +{bng_bang2(x);} + +static void bng_pointer(t_bng *x, t_gpointer *gp) +{bng_bang2(x);} + +static void bng_list(t_bng *x, t_symbol *s, int ac, t_atom *av) +{bng_bang2(x);} + +static void bng_anything(t_bng *x, t_symbol *s, int argc, t_atom *argv) +{bng_bang2(x);} + +static void bng_loadbang(t_bng *x, t_floatarg action) +{ + if (action == LB_LOAD && x->x_gui.x_isa.x_loadinit) + { + bng_set(x); + bng_bout2(x); + } +} + +static void bng_size(t_bng *x, t_symbol *s, int ac, t_atom *av) +{ + x->x_gui.x_w = iemgui_clip_size((int)atom_getfloatarg(0, ac, av)) * IEMGUI_ZOOM(x); + x->x_gui.x_h = x->x_gui.x_w; + iemgui_size((void *)x, &x->x_gui); +} + +static void bng_delta(t_bng *x, t_symbol *s, int ac, t_atom *av) +{iemgui_delta((void *)x, &x->x_gui, s, ac, av);} + +static void bng_pos(t_bng *x, t_symbol *s, int ac, t_atom *av) +{iemgui_pos((void *)x, &x->x_gui, s, ac, av);} + +static void bng_flashtime(t_bng *x, t_symbol *s, int ac, t_atom *av) +{ + bng_check_minmax(x, (int)atom_getfloatarg(0, ac, av), + (int)atom_getfloatarg(1, ac, av)); +} + +static void bng_color(t_bng *x, t_symbol *s, int ac, t_atom *av) +{iemgui_color((void *)x, &x->x_gui, s, ac, av);} + +static void bng_send(t_bng *x, t_symbol *s) +{iemgui_send(x, &x->x_gui, s);} + +static void bng_receive(t_bng *x, t_symbol *s) +{iemgui_receive(x, &x->x_gui, s);} + +static void bng_label(t_bng *x, t_symbol *s) +{iemgui_label((void *)x, &x->x_gui, s);} + +static void bng_label_pos(t_bng *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);} + +static void bng_label_font(t_bng *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);} + +static void bng_init(t_bng *x, t_floatarg f) +{ + x->x_gui.x_isa.x_loadinit = (f == 0.0) ? 0 : 1; +} + +static void bng_tick_hld(t_bng *x) +{ + x->x_flashed = 0; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); +} + +static void bng_tick_lck(t_bng *x) +{ + x->x_gui.x_isa.x_locked = 0; +} + +static void *bng_new(t_symbol *s, int argc, t_atom *argv) +{ + t_bng *x = (t_bng *)pd_new(bng_class); + int a = IEM_GUI_DEFAULTSIZE; + int ldx = 17, ldy = 7; + int fs = 10; + int ftbreak = IEM_BNG_DEFAULTBREAKFLASHTIME, + fthold = IEM_BNG_DEFAULTHOLDFLASHTIME; + char str[144]; + + iem_inttosymargs(&x->x_gui.x_isa, 0); + iem_inttofstyle(&x->x_gui.x_fsf, 0); + + x->x_gui.x_bcol = 0xFCFCFC; + x->x_gui.x_fcol = 0x00; + x->x_gui.x_lcol = 0x00; + + if((argc == 14)&&IS_A_FLOAT(argv,0) + &&IS_A_FLOAT(argv,1)&&IS_A_FLOAT(argv,2) + &&IS_A_FLOAT(argv,3) + &&(IS_A_SYMBOL(argv,4)||IS_A_FLOAT(argv,4)) + &&(IS_A_SYMBOL(argv,5)||IS_A_FLOAT(argv,5)) + &&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6)) + &&IS_A_FLOAT(argv,7)&&IS_A_FLOAT(argv,8) + &&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10)) + { + + a = (int)atom_getfloatarg(0, argc, argv); + fthold = (int)atom_getfloatarg(1, argc, argv); + ftbreak = (int)atom_getfloatarg(2, argc, argv); + iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(3, argc, argv)); + iemgui_new_getnames(&x->x_gui, 4, argv); + ldx = (int)atom_getfloatarg(7, argc, argv); + ldy = (int)atom_getfloatarg(8, argc, argv); + iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(9, argc, argv)); + fs = (int)atom_getfloatarg(10, argc, argv); + iemgui_all_loadcolors(&x->x_gui, argv+11, argv+12, argv+13); + } + else iemgui_new_getnames(&x->x_gui, 4, 0); + + x->x_gui.x_draw = (t_iemfunptr)bng_draw; + + x->x_gui.x_fsf.x_snd_able = 1; + x->x_gui.x_fsf.x_rcv_able = 1; + x->x_flashed = 0; + x->x_gui.x_glist = (t_glist *)canvas_getcurrent(); + if (!strcmp(x->x_gui.x_snd->s_name, "empty")) + x->x_gui.x_fsf.x_snd_able = 0; + if (!strcmp(x->x_gui.x_rcv->s_name, "empty")) + x->x_gui.x_fsf.x_rcv_able = 0; + if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica"); + else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times"); + else { x->x_gui.x_fsf.x_font_style = 0; + strcpy(x->x_gui.x_font, sys_font); } + + if (x->x_gui.x_fsf.x_rcv_able) + pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + x->x_gui.x_ldx = ldx; + x->x_gui.x_ldy = ldy; + + if(fs < 4) + fs = 4; + x->x_gui.x_fontsize = fs; + x->x_gui.x_w = iemgui_clip_size(a); + x->x_gui.x_h = x->x_gui.x_w; + bng_check_minmax(x, ftbreak, fthold); + x->x_gui.x_isa.x_locked = 0; + iemgui_verify_snd_ne_rcv(&x->x_gui); + x->x_lastflashtime = clock_getsystime(); + x->x_clock_hld = clock_new(x, (t_method)bng_tick_hld); + x->x_clock_lck = clock_new(x, (t_method)bng_tick_lck); + iemgui_newzoom(&x->x_gui); + outlet_new(&x->x_gui.x_obj, &s_bang); + return (x); +} + +static void bng_ff(t_bng *x) +{ + if(x->x_gui.x_fsf.x_rcv_able) + pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + clock_free(x->x_clock_lck); + clock_free(x->x_clock_hld); + gfxstub_deleteforkey(x); +} + +void g_bang_setup(void) +{ + bng_class = class_new(gensym("bng"), (t_newmethod)bng_new, + (t_method)bng_ff, sizeof(t_bng), 0, A_GIMME, 0); + class_addbang(bng_class, bng_bang); + class_addfloat(bng_class, bng_float); + class_addsymbol(bng_class, bng_symbol); + class_addpointer(bng_class, bng_pointer); + class_addlist(bng_class, bng_list); + class_addanything(bng_class, bng_anything); + class_addmethod(bng_class, (t_method)bng_click, + gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(bng_class, (t_method)bng_dialog, + gensym("dialog"), A_GIMME, 0); + class_addmethod(bng_class, (t_method)bng_loadbang, + gensym("loadbang"), A_DEFFLOAT, 0); + class_addmethod(bng_class, (t_method)bng_size, + gensym("size"), A_GIMME, 0); + class_addmethod(bng_class, (t_method)bng_delta, + gensym("delta"), A_GIMME, 0); + class_addmethod(bng_class, (t_method)bng_pos, + gensym("pos"), A_GIMME, 0); + class_addmethod(bng_class, (t_method)bng_flashtime, + gensym("flashtime"), A_GIMME, 0); + class_addmethod(bng_class, (t_method)bng_color, + gensym("color"), A_GIMME, 0); + class_addmethod(bng_class, (t_method)bng_send, + gensym("send"), A_DEFSYM, 0); + class_addmethod(bng_class, (t_method)bng_receive, + gensym("receive"), A_DEFSYM, 0); + class_addmethod(bng_class, (t_method)bng_label, + gensym("label"), A_DEFSYM, 0); + class_addmethod(bng_class, (t_method)bng_label_pos, + gensym("label_pos"), A_GIMME, 0); + class_addmethod(bng_class, (t_method)bng_label_font, + gensym("label_font"), A_GIMME, 0); + class_addmethod(bng_class, (t_method)bng_init, + gensym("init"), A_FLOAT, 0); + class_addmethod(bng_class, (t_method)iemgui_zoom, + gensym("zoom"), A_CANT, 0); + bng_widgetbehavior.w_getrectfn = bng_getrect; + bng_widgetbehavior.w_displacefn = iemgui_displace; + bng_widgetbehavior.w_selectfn = iemgui_select; + bng_widgetbehavior.w_activatefn = NULL; + bng_widgetbehavior.w_deletefn = iemgui_delete; + bng_widgetbehavior.w_visfn = iemgui_vis; + bng_widgetbehavior.w_clickfn = bng_newclick; + class_setwidget(bng_class, &bng_widgetbehavior); + class_sethelpsymbol(bng_class, gensym("bng")); + class_setsavefn(bng_class, bng_save); + class_setpropertiesfn(bng_class, bng_properties); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_canvas.c b/ports/camomile/source/LibPd/pure-data/src/g_canvas.c new file mode 100644 index 00000000..02c2c555 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_canvas.c @@ -0,0 +1,1845 @@ +/* Copyright (c) 1997-2001 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* this file defines the "glist" class, also known as "canvas" (the two used +to be different but are now unified except for some fossilized names.) */ + +#include +#include +#include "m_pd.h" +#include "m_imp.h" +#include "s_stuff.h" +#include "s_utf8.h" +#include "g_canvas.h" +#include +#include "g_all_guis.h" + +#ifdef _MSC_VER +#include +#define snprintf _snprintf +#endif + + /* LATER consider adding font size to this struct (see glist_getfont()) */ +struct _canvasenvironment +{ + t_symbol *ce_dir; /* directory patch lives in */ + int ce_argc; /* number of "$" arguments */ + t_atom *ce_argv; /* array of "$" arguments */ + int ce_dollarzero; /* value of "$0" */ + t_namelist *ce_path; /* search path */ +}; + +#define GLIST_DEFCANVASWIDTH 450 +#define GLIST_DEFCANVASHEIGHT 300 + +/* since the window decorations aren't included, open new windows a few +pixels down so you can posibly move the window later. Apple needs less +because its menus are at top of screen; we're more generous for other +desktops because the borders have both window title area and menus. */ +#ifdef __APPLE__ +#define GLIST_DEFCANVASYLOC 22 +#else +#define GLIST_DEFCANVASYLOC 50 +#endif + +/* ---------------------- variables --------------------------- */ + +t_class *canvas_class; +t_canvas *canvas_whichfind; /* last canvas we did a find in */ + +/* ------------------ forward function declarations --------------- */ +static void canvas_start_dsp(void); +static void canvas_stop_dsp(void); +static void canvas_drawlines(t_canvas *x); +static void canvas_dosetbounds(t_canvas *x, int x1, int y1, int x2, int y2); +void canvas_reflecttitle(t_canvas *x); +static void canvas_addtolist(t_canvas *x); +static void canvas_takeofflist(t_canvas *x); +static void canvas_pop(t_canvas *x, t_floatarg fvis); +static void canvas_bind(t_canvas *x); +static void canvas_unbind(t_canvas *x); +void canvas_declare(t_canvas *x, t_symbol *s, int argc, t_atom *argv); + +/* --------- functions to handle the canvas environment ----------- */ + + + /* maintain the list of visible toplevels for the GUI's "windows" menu */ +void canvas_updatewindowlist( void) +{ + /* not if we're in a reload */ + if (!THISGUI->i_reloadingabstraction) + sys_gui("::pd_menus::update_window_menu\n"); +} + + /* add a glist the list of "root" canvases (toplevels without parents.) */ +static void canvas_addtolist(t_canvas *x) +{ + x->gl_next = pd_this->pd_canvaslist; + pd_this->pd_canvaslist = x; +} + +static void canvas_takeofflist(t_canvas *x) +{ + /* take it off the window list */ + if (x == pd_this->pd_canvaslist) pd_this->pd_canvaslist = x->gl_next; + else + { + t_canvas *z; + for (z = pd_this->pd_canvaslist; z->gl_next != x; z = z->gl_next) + if (!z->gl_next) return; + z->gl_next = x->gl_next; + } +} + + +void canvas_setargs(int argc, t_atom *argv) +{ + /* if there's an old one lying around free it here. This + happens if an abstraction is loaded but never gets as far + as calling canvas_new(). */ + if (THISGUI->i_newargv) + freebytes(THISGUI->i_newargv, THISGUI->i_newargc * sizeof(t_atom)); + THISGUI->i_newargc = argc; + THISGUI->i_newargv = copybytes(argv, argc * sizeof(t_atom)); +} + +void glob_setfilename(void *dummy, t_symbol *filesym, t_symbol *dirsym) +{ + THISGUI->i_newfilename = filesym; + THISGUI->i_newdirectory = dirsym; +} + +void glob_menunew(void *dummy, t_symbol *filesym, t_symbol *dirsym) +{ + glob_setfilename(dummy, filesym, dirsym); + canvas_new(0, 0, 0, 0); + canvas_pop((t_canvas *)s__X.s_thing, 1); +} + +t_canvas *canvas_getcurrent(void) +{ + return ((t_canvas *)pd_findbyclass(&s__X, canvas_class)); +} + +void canvas_setcurrent(t_canvas *x) +{ + pd_pushsym(&x->gl_pd); +} + +void canvas_unsetcurrent(t_canvas *x) +{ + pd_popsym(&x->gl_pd); +} + +t_canvasenvironment *canvas_getenv(t_canvas *x) +{ + if (!x) bug("canvas_getenv"); + while (!x->gl_env) + if (!(x = x->gl_owner)) + bug("t_canvasenvironment"); + return (x->gl_env); +} + +int canvas_getdollarzero( void) +{ + t_canvas *x = canvas_getcurrent(); + t_canvasenvironment *env = (x ? canvas_getenv(x) : 0); + if (env) + return (env->ce_dollarzero); + else return (0); +} + +void canvas_getargs(int *argcp, t_atom **argvp) +{ + t_canvas *x = canvas_getcurrent(); + t_canvasenvironment *e = canvas_getenv(x); + *argcp = e->ce_argc; + *argvp = e->ce_argv; +} + +t_symbol *canvas_realizedollar(t_canvas *x, t_symbol *s) +{ + t_symbol *ret; + char *name = s->s_name; + if (strchr(name, '$')) + { + t_canvasenvironment *env = canvas_getenv(x); + canvas_setcurrent(x); + ret = binbuf_realizedollsym(s, env->ce_argc, env->ce_argv, 1); + canvas_unsetcurrent(x); + } + else ret = s; + return (ret); +} + +t_symbol *canvas_getcurrentdir(void) +{ + t_canvasenvironment *e = canvas_getenv(canvas_getcurrent()); + return (e->ce_dir); +} + +t_symbol *canvas_getdir(t_canvas *x) +{ + t_canvasenvironment *e = canvas_getenv(x); + return (e->ce_dir); +} + +void canvas_makefilename(t_canvas *x, char *file, char *result, int resultsize) +{ + char *dir = canvas_getenv(x)->ce_dir->s_name; + if (file[0] == '/' || (file[0] && file[1] == ':') || !*dir) + { + strncpy(result, file, resultsize); + result[resultsize-1] = 0; + } + else + { + int nleft; + strncpy(result, dir, resultsize); + result[resultsize-1] = 0; + nleft = resultsize - (int)strlen(result) - 1; + if (nleft <= 0) return; + strcat(result, "/"); + strncat(result, file, nleft); + result[resultsize-1] = 0; + } +} + +void canvas_rename(t_canvas *x, t_symbol *s, t_symbol *dir) +{ + canvas_unbind(x); + x->gl_name = s; + canvas_bind(x); + if (x->gl_havewindow) + canvas_reflecttitle(x); + if (dir && dir != &s_) + { + t_canvasenvironment *e = canvas_getenv(x); + e->ce_dir = dir; + } +} + +/* --------------- traversing the set of lines in a canvas ----------- */ + +int canvas_getindex(t_canvas *x, t_gobj *y) +{ + t_gobj *y2; + int indexno; + for (indexno = 0, y2 = x->gl_list; y2 && y2 != y; y2 = y2->g_next) + indexno++; + return (indexno); +} + +void linetraverser_start(t_linetraverser *t, t_canvas *x) +{ + t->tr_ob = 0; + t->tr_x = x; + t->tr_nextoc = 0; + t->tr_nextoutno = t->tr_nout = 0; +} + +t_outconnect *linetraverser_next(t_linetraverser *t) +{ + t_outconnect *rval = t->tr_nextoc; + int outno; + while (!rval) + { + outno = t->tr_nextoutno; + while (outno == t->tr_nout) + { + t_gobj *y; + t_object *ob = 0; + if (!t->tr_ob) y = t->tr_x->gl_list; + else y = t->tr_ob->ob_g.g_next; + for (; y; y = y->g_next) + if ((ob = pd_checkobject(&y->g_pd))) break; + if (!ob) return (0); + t->tr_ob = ob; + t->tr_nout = obj_noutlets(ob); + outno = 0; + if (glist_isvisible(t->tr_x)) + gobj_getrect(y, t->tr_x, + &t->tr_x11, &t->tr_y11, &t->tr_x12, &t->tr_y12); + else t->tr_x11 = t->tr_y11 = t->tr_x12 = t->tr_y12 = 0; + } + t->tr_nextoutno = outno + 1; + rval = obj_starttraverseoutlet(t->tr_ob, &t->tr_outlet, outno); + t->tr_outno = outno; + } + t->tr_nextoc = obj_nexttraverseoutlet(rval, &t->tr_ob2, + &t->tr_inlet, &t->tr_inno); + t->tr_nin = obj_ninlets(t->tr_ob2); + if (!t->tr_nin) bug("drawline"); + if (glist_isvisible(t->tr_x)) + { + int inplus = (t->tr_nin == 1 ? 1 : t->tr_nin - 1); + int outplus = (t->tr_nout == 1 ? 1 : t->tr_nout - 1); + int iow = IOWIDTH * t->tr_x->gl_zoom; + int iom = IOMIDDLE * t->tr_x->gl_zoom; + gobj_getrect(&t->tr_ob2->ob_g, t->tr_x, + &t->tr_x21, &t->tr_y21, &t->tr_x22, &t->tr_y22); + t->tr_lx1 = t->tr_x11 + + ((t->tr_x12 - t->tr_x11 - iow) * t->tr_outno) / + outplus + iom; + t->tr_ly1 = t->tr_y12; + t->tr_lx2 = t->tr_x21 + + ((t->tr_x22 - t->tr_x21 - iow) * t->tr_inno)/inplus + + iom; + t->tr_ly2 = t->tr_y21; + } + else + { + t->tr_x21 = t->tr_y21 = t->tr_x22 = t->tr_y22 = 0; + t->tr_lx1 = t->tr_ly1 = t->tr_lx2 = t->tr_ly2 = 0; + } + + return (rval); +} + +void linetraverser_skipobject(t_linetraverser *t) +{ + t->tr_nextoc = 0; + t->tr_nextoutno = t->tr_nout; +} + +/* -------------------- the canvas object -------------------------- */ +int glist_valid = 10000; + +void glist_init(t_glist *x) +{ + /* zero out everyone except "pd" field */ + memset(((char *)x) + sizeof(x->gl_pd), 0, sizeof(*x) - sizeof(x->gl_pd)); + x->gl_stub = gstub_new(x, 0); + x->gl_valid = ++glist_valid; + x->gl_xlabel = (t_symbol **)t_getbytes(0); + x->gl_ylabel = (t_symbol **)t_getbytes(0); +} + + /* make a new glist. It will either be a "root" canvas or else + it appears as a "text" object in another window (canvas_getcurrent() + tells us which.) */ +t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv) +{ + t_canvas *x = (t_canvas *)pd_new(canvas_class); + t_canvas *owner = canvas_getcurrent(); + t_symbol *s = &s_; + int vis = 0, width = GLIST_DEFCANVASWIDTH, height = GLIST_DEFCANVASHEIGHT; + int xloc = 0, yloc = GLIST_DEFCANVASYLOC; + int font = (owner ? owner->gl_font : sys_defaultfont); + glist_init(x); + x->gl_obj.te_type = T_OBJECT; + if (!owner) + canvas_addtolist(x); + /* post("canvas %lx, owner %lx", x, owner); */ + + if (argc == 5) /* toplevel: x, y, w, h, font */ + { + xloc = atom_getfloatarg(0, argc, argv); + yloc = atom_getfloatarg(1, argc, argv); + width = atom_getfloatarg(2, argc, argv); + height = atom_getfloatarg(3, argc, argv); + font = atom_getfloatarg(4, argc, argv); + } + else if (argc == 6) /* subwindow: x, y, w, h, name, vis */ + { + xloc = atom_getfloatarg(0, argc, argv); + yloc = atom_getfloatarg(1, argc, argv); + width = atom_getfloatarg(2, argc, argv); + height = atom_getfloatarg(3, argc, argv); + s = atom_getsymbolarg(4, argc, argv); + vis = atom_getfloatarg(5, argc, argv); + } + /* (otherwise assume we're being created from the menu.) */ + if (THISGUI->i_newdirectory && + THISGUI->i_newdirectory->s_name[0]) + { + t_canvasenvironment *env = x->gl_env = + (t_canvasenvironment *)getbytes(sizeof(*x->gl_env)); + if (!THISGUI->i_newargv) + THISGUI->i_newargv = getbytes(0); + env->ce_dir = THISGUI->i_newdirectory; + env->ce_argc = THISGUI->i_newargc; + env->ce_argv = THISGUI->i_newargv; + env->ce_dollarzero = THISGUI->i_dollarzero++; + env->ce_path = 0; + THISGUI->i_newdirectory = &s_; + THISGUI->i_newargc = 0; + THISGUI->i_newargv = 0; + } + else x->gl_env = 0; + + x->gl_x1 = 0; + x->gl_y1 = 0; + x->gl_x2 = 1; + x->gl_y2 = 1; + canvas_dosetbounds(x, xloc, yloc, xloc + width, yloc + height); + x->gl_owner = owner; + x->gl_isclone = 0; + x->gl_name = (*s->s_name ? s : + (THISGUI->i_newfilename ? THISGUI->i_newfilename : gensym("Pd"))); + canvas_bind(x); + x->gl_loading = 1; + x->gl_goprect = 0; /* no GOP rectangle unless it's turned on later */ + /* cancel "vis" flag if we're a subpatch of an + abstraction inside another patch. A separate mechanism prevents + the toplevel abstraction from showing up. */ + if (vis && gensym("#X")->s_thing && + ((*gensym("#X")->s_thing) == canvas_class)) + { + t_canvas *zzz = (t_canvas *)(gensym("#X")->s_thing); + while (zzz && !zzz->gl_env) + zzz = zzz->gl_owner; + if (zzz && canvas_isabstraction(zzz) && zzz->gl_owner) + vis = 0; + } + x->gl_willvis = vis; + x->gl_edit = !strncmp(x->gl_name->s_name, "Untitled", 8); + x->gl_font = sys_nearestfontsize(font); + x->gl_zoom = 1; + pd_pushsym(&x->gl_pd); + return(x); +} + +void canvas_setgraph(t_glist *x, int flag, int nogoprect); + +static void canvas_coords(t_glist *x, t_symbol *s, int argc, t_atom *argv) +{ + x->gl_x1 = atom_getfloatarg(0, argc, argv); + x->gl_y1 = atom_getfloatarg(1, argc, argv); + x->gl_x2 = atom_getfloatarg(2, argc, argv); + x->gl_y2 = atom_getfloatarg(3, argc, argv); + x->gl_pixwidth = atom_getfloatarg(4, argc, argv); + x->gl_pixheight = atom_getfloatarg(5, argc, argv); + if (argc <= 7) + canvas_setgraph(x, atom_getfloatarg(6, argc, argv), 1); + else + { + x->gl_xmargin = atom_getfloatarg(7, argc, argv); + x->gl_ymargin = atom_getfloatarg(8, argc, argv); + canvas_setgraph(x, atom_getfloatarg(6, argc, argv), 0); + } +} + + /* make a new glist and add it to this glist. It will appear as + a "graph", not a text object. */ +t_glist *glist_addglist(t_glist *g, t_symbol *sym, + t_float x1, t_float y1, t_float x2, t_float y2, + t_float px1, t_float py1, t_float px2, t_float py2) +{ + static int gcount = 0; /* it's OK if two threads get the same value */ + int zz; + int menu = 0; + char *str; + t_glist *x = (t_glist *)pd_new(canvas_class); + glist_init(x); + x->gl_obj.te_type = T_OBJECT; + if (!*sym->s_name) + { + char buf[40]; + sprintf(buf, "graph%d", ++gcount); + sym = gensym(buf); + menu = 1; + } + else if (!strncmp((str = sym->s_name), "graph", 5) + && (zz = atoi(str + 5)) > gcount) + gcount = zz; + /* in 0.34 and earlier, the pixel rectangle and the y bounds were + reversed; this would behave the same, except that the dialog window + would be confusing. The "correct" way is to have "py1" be the value + that is higher on the screen. */ + if (py2 < py1) + { + t_float zz; + zz = y2; + y2 = y1; + y1 = zz; + zz = py2; + py2 = py1; + py1 = zz; + } + if (x1 == x2 || y1 == y2) + x1 = 0, x2 = 100, y1 = 1, y2 = -1; + if (px1 >= px2 || py1 >= py2) + px1 = 100, py1 = 20, px2 = 100 + GLIST_DEFGRAPHWIDTH, + py2 = 20 + GLIST_DEFGRAPHHEIGHT; + x->gl_name = sym; + x->gl_x1 = x1; + x->gl_x2 = x2; + x->gl_y1 = y1; + x->gl_y2 = y2; + x->gl_obj.te_xpix = px1; + x->gl_obj.te_ypix = py1; + x->gl_pixwidth = px2 - px1; + x->gl_pixheight = py2 - py1; + x->gl_font = (canvas_getcurrent() ? + canvas_getcurrent()->gl_font : sys_defaultfont); + x->gl_zoom = 1; + x->gl_screenx1 = 0; + x->gl_screeny1 = GLIST_DEFCANVASYLOC; + x->gl_screenx2 = 450; + x->gl_screeny2 = 300; + x->gl_owner = g; + canvas_bind(x); + x->gl_isgraph = 1; + x->gl_goprect = 0; + x->gl_obj.te_binbuf = binbuf_new(); + binbuf_addv(x->gl_obj.te_binbuf, "s", gensym("graph")); + if (!menu) + pd_pushsym(&x->gl_pd); + glist_add(g, &x->gl_gobj); + return (x); +} + + /* call glist_addglist from a Pd message */ +void glist_glist(t_glist *g, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *sym = atom_getsymbolarg(0, argc, argv); + t_float x1 = atom_getfloatarg(1, argc, argv); + t_float y1 = atom_getfloatarg(2, argc, argv); + t_float x2 = atom_getfloatarg(3, argc, argv); + t_float y2 = atom_getfloatarg(4, argc, argv); + t_float px1 = atom_getfloatarg(5, argc, argv); + t_float py1 = atom_getfloatarg(6, argc, argv); + t_float px2 = atom_getfloatarg(7, argc, argv); + t_float py2 = atom_getfloatarg(8, argc, argv); + glist_addglist(g, sym, x1, y1, x2, y2, px1, py1, px2, py2); +} + + /* return true if the glist should appear as a graph on parent; + otherwise it appears as a text box. */ +int glist_isgraph(t_glist *x) +{ + return (x->gl_isgraph|(x->gl_hidetext<<1)); +} + + /* This is sent from the GUI to inform a toplevel that its window has been + moved or resized. */ +static void canvas_setbounds(t_canvas *x, t_float left, t_float top, + t_float right, t_float bottom) +{ + canvas_dosetbounds(x, (int)left, (int)top, (int)right, (int)bottom); +} + +/* this is the internal version using ints */ +static void canvas_dosetbounds(t_canvas *x, int x1, int y1, int x2, int y2) +{ + int heightwas = y2 - y1; + int heightchange = y2 - y1 - (x->gl_screeny2 - x->gl_screeny1); + if (x->gl_screenx1 == x1 && x->gl_screeny1 == y1 && + x->gl_screenx2 == x2 && x->gl_screeny2 == y2) + return; + x->gl_screenx1 = x1; + x->gl_screeny1 = y1; + x->gl_screenx2 = x2; + x->gl_screeny2 = y2; + if (!glist_isgraph(x) && (x->gl_y2 < x->gl_y1)) + { + /* if it's flipped so that y grows upward, + fix so that zero is bottom edge and redraw. This is + only appropriate if we're a regular "text" object on the + parent. */ + t_float diff = x->gl_y1 - x->gl_y2; + t_gobj *y; + x->gl_y1 = heightwas * diff; + x->gl_y2 = x->gl_y1 - diff; + /* and move text objects accordingly; they should stick + to the bottom, not the top. */ + for (y = x->gl_list; y; y = y->g_next) + if (pd_checkobject(&y->g_pd)) + gobj_displace(y, x, 0, heightchange); + canvas_redraw(x); + } +} + +t_symbol *canvas_makebindsym(t_symbol *s) +{ + char buf[MAXPDSTRING]; + snprintf(buf, MAXPDSTRING-1, "pd-%s", s->s_name); + buf[MAXPDSTRING-1] = 0; + return (gensym(buf)); +} + + /* functions to bind and unbind canvases to symbol "pd-blah". As + discussed on Pd dev list there should be a way to defeat this for + abstractions. (Claude Heiland et al. Aug 9 2013) */ +static void canvas_bind(t_canvas *x) +{ + if (strcmp(x->gl_name->s_name, "Pd")) + pd_bind(&x->gl_pd, canvas_makebindsym(x->gl_name)); +} + +static void canvas_unbind(t_canvas *x) +{ + if (strcmp(x->gl_name->s_name, "Pd")) + pd_unbind(&x->gl_pd, canvas_makebindsym(x->gl_name)); +} + +void canvas_reflecttitle(t_canvas *x) +{ + char namebuf[MAXPDSTRING]; + t_canvasenvironment *env = canvas_getenv(x); + if (env->ce_argc) + { + int i; + strcpy(namebuf, " ("); + for (i = 0; i < env->ce_argc; i++) + { + if (strlen(namebuf) > MAXPDSTRING/2 - 5) + break; + if (i != 0) + strcat(namebuf, " "); + atom_string(&env->ce_argv[i], namebuf + strlen(namebuf), + MAXPDSTRING/2); + } + strcat(namebuf, ")"); + } + else namebuf[0] = 0; + if (x->gl_edit) + { + strncat(namebuf, " *edit*", MAXPDSTRING); + namebuf[MAXPDSTRING-1] = 0; + } + sys_vgui("pdtk_canvas_reflecttitle .x%lx {%s} {%s} {%s} %d\n", + x, canvas_getdir(x)->s_name, x->gl_name->s_name, namebuf, x->gl_dirty); +} + + /* mark a glist dirty or clean */ +void canvas_dirty(t_canvas *x, t_floatarg n) +{ + t_canvas *x2 = canvas_getrootfor(x); + if (THISGUI->i_reloadingabstraction) + return; + if ((unsigned)n != x2->gl_dirty) + { + x2->gl_dirty = n; + if (x2->gl_havewindow) + canvas_reflecttitle(x2); + } +} + +void canvas_drawredrect(t_canvas *x, int doit) +{ + if (doit) + sys_vgui(".x%lx.c create line %d %d %d %d %d %d %d %d %d %d " + "-fill #ff8080 -width %d -capstyle projecting -tags GOP\n", + glist_getcanvas(x), + x->gl_xmargin, x->gl_ymargin, + x->gl_xmargin + x->gl_pixwidth, x->gl_ymargin, + x->gl_xmargin + x->gl_pixwidth, x->gl_ymargin + x->gl_pixheight, + x->gl_xmargin, x->gl_ymargin + x->gl_pixheight, + x->gl_xmargin, x->gl_ymargin, glist_getzoom(x)); + else sys_vgui(".x%lx.c delete GOP\n", glist_getcanvas(x)); +} + + /* the window becomes "mapped" (visible and not miniaturized) or + "unmapped" (either miniaturized or just plain gone.) This should be + called from the GUI after the fact to "notify" us that we're mapped. */ +void canvas_map(t_canvas *x, t_floatarg f) +{ + int flag = (f != 0); + t_gobj *y; + if (flag) + { + if (!glist_isvisible(x)) + { + t_selection *sel; + if (!x->gl_havewindow) + { + bug("canvas_map"); + canvas_vis(x, 1); + } + for (y = x->gl_list; y; y = y->g_next) + gobj_vis(y, x, 1); + x->gl_mapped = 1; + for (sel = x->gl_editor->e_selection; sel; sel = sel->sel_next) + gobj_select(sel->sel_what, x, 1); + canvas_drawlines(x); + if (x->gl_isgraph && x->gl_goprect) + canvas_drawredrect(x, 1); + sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x); + } + } + else + { + if (glist_isvisible(x)) + { + /* just clear out the whole canvas */ + sys_vgui(".x%lx.c delete all\n", x); + x->gl_mapped = 0; + } + } +} + +void canvas_redraw(t_canvas *x) +{ + if (glist_isvisible(x)) + { + canvas_map(x, 0); + canvas_map(x, 1); + } +} + + + /* we call this on a non-toplevel glist to "open" it into its + own window. */ +void glist_menu_open(t_glist *x) +{ + if (glist_isvisible(x) && !glist_istoplevel(x)) + { + t_glist *gl2 = x->gl_owner; + if (!gl2) + bug("glist_menu_open"); /* shouldn't happen but not dangerous */ + else + { + /* erase ourself in parent window */ + gobj_vis(&x->gl_gobj, gl2, 0); + /* get rid of our editor (and subeditors) */ + if (x->gl_editor) + canvas_destroy_editor(x); + x->gl_havewindow = 1; + /* redraw ourself in parent window (blanked out this time) */ + gobj_vis(&x->gl_gobj, gl2, 1); + } + } + canvas_vis(x, 1); +} + +int glist_isvisible(t_glist *x) +{ + return ((!x->gl_loading) && glist_getcanvas(x)->gl_mapped); +} + +int glist_istoplevel(t_glist *x) +{ + /* we consider a graph "toplevel" if it has its own window + or if it appears as a box in its parent window so that we + don't draw the actual contents there. */ + return (x->gl_havewindow || !x->gl_isgraph); +} + +int glist_getfont(t_glist *x) +{ + while (!x->gl_env) + if (!(x = x->gl_owner)) + bug("t_canvasenvironment"); + return (x->gl_font); +} + +int glist_getzoom(t_glist *x) +{ + t_glist *gl2 = x; + while (!glist_istoplevel(gl2) && gl2->gl_owner) + gl2 = gl2->gl_owner; + return (gl2->gl_zoom); +} + +int glist_fontwidth(t_glist *x) +{ + return (sys_zoomfontwidth(glist_getfont(x), glist_getzoom(x), 0)); +} + +int glist_fontheight(t_glist *x) +{ + return (sys_zoomfontheight(glist_getfont(x), glist_getzoom(x), 0)); +} + +void canvas_free(t_canvas *x) +{ + t_gobj *y; + int dspstate = canvas_suspend_dsp(); + canvas_noundo(x); + if (canvas_whichfind == x) + canvas_whichfind = 0; + glist_noselect(x); + while ((y = x->gl_list)) + glist_delete(x, y); + if (x == glist_getcanvas(x)) + canvas_vis(x, 0); + if (x->gl_editor) + canvas_destroy_editor(x); /* bug workaround; should already be gone*/ + canvas_unbind(x); + + if (x->gl_env) + { + freebytes(x->gl_env->ce_argv, x->gl_env->ce_argc * sizeof(t_atom)); + freebytes(x->gl_env, sizeof(*x->gl_env)); + } + canvas_resume_dsp(dspstate); + freebytes(x->gl_xlabel, x->gl_nxlabels * sizeof(*(x->gl_xlabel))); + freebytes(x->gl_ylabel, x->gl_nylabels * sizeof(*(x->gl_ylabel))); + gstub_cutoff(x->gl_stub); + gfxstub_deleteforkey(x); /* probably unnecessary */ + if (!x->gl_owner && !x->gl_isclone) + canvas_takeofflist(x); +} + +/* ----------------- lines ---------- */ + +static void canvas_drawlines(t_canvas *x) +{ + t_linetraverser t; + t_outconnect *oc; + { + linetraverser_start(&t, x); + while ((oc = linetraverser_next(&t))) + sys_vgui( + ".x%lx.c create line %d %d %d %d -width %d -tags [list l%lx cord]\n", + glist_getcanvas(x), + t.tr_lx1, t.tr_ly1, t.tr_lx2, t.tr_ly2, + (outlet_getsymbol(t.tr_outlet) == &s_signal ? 2:1) * x->gl_zoom, + oc); + } +} + +void canvas_fixlinesfor(t_canvas *x, t_text *text) +{ + t_linetraverser t; + t_outconnect *oc; + + linetraverser_start(&t, x); + while ((oc = linetraverser_next(&t))) + { + if (t.tr_ob == text || t.tr_ob2 == text) + { + sys_vgui(".x%lx.c coords l%lx %d %d %d %d\n", + glist_getcanvas(x), oc, + t.tr_lx1, t.tr_ly1, t.tr_lx2, t.tr_ly2); + } + } +} + + /* kill all lines for the object */ +void canvas_deletelinesfor(t_canvas *x, t_text *text) +{ + t_linetraverser t; + t_outconnect *oc; + linetraverser_start(&t, x); + while ((oc = linetraverser_next(&t))) + { + if (t.tr_ob == text || t.tr_ob2 == text) + { + if (glist_isvisible(x)) + { + sys_vgui(".x%lx.c delete l%lx\n", + glist_getcanvas(x), oc); + } + obj_disconnect(t.tr_ob, t.tr_outno, t.tr_ob2, t.tr_inno); + } + } +} + + /* kill all lines for one inlet or outlet */ +void canvas_deletelinesforio(t_canvas *x, t_text *text, + t_inlet *inp, t_outlet *outp) +{ + t_linetraverser t; + t_outconnect *oc; + linetraverser_start(&t, x); + while ((oc = linetraverser_next(&t))) + { + if ((t.tr_ob == text && t.tr_outlet == outp) || + (t.tr_ob2 == text && t.tr_inlet == inp)) + { + if (glist_isvisible(x)) + { + sys_vgui(".x%lx.c delete l%lx\n", + glist_getcanvas(x), oc); + } + obj_disconnect(t.tr_ob, t.tr_outno, t.tr_ob2, t.tr_inno); + } + } +} + +typedef void (*t_zoomfn)(void *x, t_floatarg arg1); + +static void canvas_pop(t_canvas *x, t_floatarg fvis) +{ + if (glist_istoplevel(x) && (sys_zoom_open == 2)) + { + t_zoomfn zoommethod = (t_zoomfn)zgetfn(&x->gl_pd, gensym("zoom")); + if (zoommethod) + (*zoommethod)(&x->gl_pd, (t_floatarg)2); + } + if (fvis != 0) + canvas_vis(x, 1); + pd_popsym(&x->gl_pd); + canvas_resortinlets(x); + canvas_resortoutlets(x); + x->gl_loading = 0; +} + +void canvas_objfor(t_glist *gl, t_text *x, int argc, t_atom *argv); + + +void canvas_restore(t_canvas *x, t_symbol *s, int argc, t_atom *argv) +{ + t_pd *z; + if (argc > 3) + { + t_atom *ap=argv+3; + if (ap->a_type == A_SYMBOL) + { + t_canvasenvironment *e = canvas_getenv(canvas_getcurrent()); + canvas_rename(x, binbuf_realizedollsym(ap->a_w.w_symbol, + e->ce_argc, e->ce_argv, 1), 0); + } + } + canvas_pop(x, x->gl_willvis); + + if (!(z = gensym("#X")->s_thing)) error("canvas_restore: out of context"); + else if (*z != canvas_class) error("canvas_restore: wasn't a canvas"); + else + { + t_canvas *x2 = (t_canvas *)z; + x->gl_owner = x2; + canvas_objfor(x2, &x->gl_obj, argc, argv); + } +} + +static void canvas_loadbangabstractions(t_canvas *x) +{ + t_gobj *y; + for (y = x->gl_list; y; y = y->g_next) + if (pd_class(&y->g_pd) == canvas_class) + { + if (canvas_isabstraction((t_canvas *)y)) + canvas_loadbang((t_canvas *)y); + else + canvas_loadbangabstractions((t_canvas *)y); + } +} + +void canvas_loadbangsubpatches(t_canvas *x) +{ + t_gobj *y; + t_symbol *s = gensym("loadbang"); + for (y = x->gl_list; y; y = y->g_next) + if (pd_class(&y->g_pd) == canvas_class) + { + if (!canvas_isabstraction((t_canvas *)y)) + canvas_loadbangsubpatches((t_canvas *)y); + } + for (y = x->gl_list; y; y = y->g_next) + if ((pd_class(&y->g_pd) != canvas_class) && + zgetfn(&y->g_pd, s)) + pd_vmess(&y->g_pd, s, "f", (t_floatarg)LB_LOAD); +} + +void canvas_loadbang(t_canvas *x) +{ + t_gobj *y; + canvas_loadbangabstractions(x); + canvas_loadbangsubpatches(x); +} + +/* JMZ/MSP: + * initbang is emitted after a canvas is read from a file, but before the + parent canvas is finished loading. This is apparently used so that + abstractions can create inlets/outlets as a function of creation arguments. + This practice is quite ugly but there's no other way to do it so far. + */ +void canvas_initbang(t_canvas *x) +{ + t_gobj *y; + t_symbol *s = gensym("loadbang"); + /* run "initbang" for all subpatches, but NOT for the child abstractions */ + for (y = x->gl_list; y; y = y->g_next) + if (pd_class(&y->g_pd) == canvas_class && + !canvas_isabstraction((t_canvas *)y)) + canvas_initbang((t_canvas *)y); + /* call the initbang()-method for objects that have one */ + for (y = x->gl_list; y; y = y->g_next) + if ((pd_class(&y->g_pd) != canvas_class) && zgetfn(&y->g_pd, s)) + pd_vmess(&y->g_pd, s, "f", (t_floatarg)LB_INIT); +} + +/* JMZ: + * closebang is emitted before the canvas is destroyed + * and BEFORE subpatches/abstractions in this canvas are destroyed + */ +void canvas_closebang(t_canvas *x) +{ + t_gobj *y; + t_symbol *s = gensym("loadbang"); + + /* call the closebang()-method for objects that have one + * but NOT for subpatches/abstractions: these are called separately + * from g_graph:glist_delete() + */ + for (y = x->gl_list; y; y = y->g_next) + if ((pd_class(&y->g_pd) != canvas_class) && zgetfn(&y->g_pd, s)) + pd_vmess(&y->g_pd, s, "f", (t_floatarg)LB_CLOSE); +} + +/* no longer used by 'pd-gui', but kept here for backwards compatibility. The + * new method calls canvas_setbounds() directly. */ +static void canvas_relocate(t_canvas *x, t_symbol *canvasgeom, + t_symbol *topgeom) +{ + int cxpix, cypix, cw, ch, txpix, typix, tw, th; + if (sscanf(canvasgeom->s_name, "%dx%d+%d+%d", &cw, &ch, &cxpix, &cypix) + < 4 || + sscanf(topgeom->s_name, "%dx%d+%d+%d", &tw, &th, &txpix, &typix) < 4) + bug("canvas_relocate"); + /* for some reason this is initially called with cw=ch=1 so + we just suppress that here. */ + if (cw > 5 && ch > 5) + canvas_dosetbounds(x, txpix, typix, + txpix + cw, typix + ch); +} + +void canvas_popabstraction(t_canvas *x) +{ + pd_this->pd_newest = &x->gl_pd; + pd_popsym(&x->gl_pd); + x->gl_loading = 0; + canvas_resortinlets(x); + canvas_resortoutlets(x); +} + +void canvas_logerror(t_object *y) +{ +#ifdef LATER + canvas_vis(x, 1); + if (!glist_isselected(x, &y->ob_g)) + glist_select(x, &y->ob_g); +#endif +} + +/* -------------------------- subcanvases ---------------------- */ + +static void *subcanvas_new(t_symbol *s) +{ + t_atom a[6]; + t_canvas *x, *z = canvas_getcurrent(); + if (!*s->s_name) s = gensym("/SUBPATCH/"); + SETFLOAT(a, 0); + SETFLOAT(a+1, GLIST_DEFCANVASYLOC); + SETFLOAT(a+2, GLIST_DEFCANVASWIDTH); + SETFLOAT(a+3, GLIST_DEFCANVASHEIGHT); + SETSYMBOL(a+4, s); + SETFLOAT(a+5, 1); + x = canvas_new(0, 0, 6, a); + x->gl_owner = z; + canvas_pop(x, 1); + return (x); +} + +static void canvas_click(t_canvas *x, + t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + canvas_vis(x, 1); +} + + + /* find out from subcanvas contents how much to fatten the box */ +void canvas_fattensub(t_canvas *x, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_gobj *y; + *xp2 += 50; /* fake for now */ + *yp2 += 50; +} + +static void canvas_rename_method(t_canvas *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac && av->a_type == A_SYMBOL) + canvas_rename(x, av->a_w.w_symbol, 0); + else if (ac && av->a_type == A_DOLLSYM) + { + t_canvasenvironment *e = canvas_getenv(x); + canvas_setcurrent(x); + canvas_rename(x, binbuf_realizedollsym(av->a_w.w_symbol, + e->ce_argc, e->ce_argv, 1), 0); + canvas_unsetcurrent(x); + } + else canvas_rename(x, gensym("Pd"), 0); +} + + + /* return true if the "canvas" object is an abstraction (so we don't + save its contents, for example.) */ +int canvas_isabstraction(t_canvas *x) +{ + return (x->gl_env != 0); +} + + /* return true if the "canvas" object should be treated as a text + object. This is true for abstractions but also for "table"s... */ +/* JMZ: add a flag to gop-abstractions to hide the title */ +int canvas_showtext(t_canvas *x) +{ + t_atom *argv = (x->gl_obj.te_binbuf? binbuf_getvec(x->gl_obj.te_binbuf):0); + int argc = (x->gl_obj.te_binbuf? binbuf_getnatom(x->gl_obj.te_binbuf) : 0); + int isarray = (argc && argv[0].a_type == A_SYMBOL && + argv[0].a_w.w_symbol == gensym("graph")); + if(x->gl_hidetext) + return 0; + else + return (!isarray); +} + + /* get the document containing this canvas */ +t_canvas *canvas_getrootfor(t_canvas *x) +{ + if ((!x->gl_owner) || canvas_isabstraction(x)) + return (x); + else return (canvas_getrootfor(x->gl_owner)); +} + +/* ------------------------- DSP chain handling ------------------------- */ + +EXTERN_STRUCT _dspcontext; +#define t_dspcontext struct _dspcontext + +void ugen_start(void); +void ugen_stop(void); + +t_dspcontext *ugen_start_graph(int toplevel, t_signal **sp, + int ninlets, int noutlets); +void ugen_add(t_dspcontext *dc, t_object *x); +void ugen_connect(t_dspcontext *dc, t_object *x1, int outno, + t_object *x2, int inno); +void ugen_done_graph(t_dspcontext *dc); + + /* schedule one canvas for DSP. This is called below for all "root" + canvases, but is also called from the "dsp" method for sub- + canvases, which are treated almost like any other tilde object. */ + +void canvas_dodsp(t_canvas *x, int toplevel, t_signal **sp) +{ + t_linetraverser t; + t_outconnect *oc; + t_gobj *y; + t_object *ob; + t_symbol *dspsym = gensym("dsp"); + t_dspcontext *dc; + + /* create a new "DSP graph" object to use in sorting this canvas. + If we aren't toplevel, there are already other dspcontexts around. */ + + dc = ugen_start_graph(toplevel, sp, + obj_nsiginlets(&x->gl_obj), + obj_nsigoutlets(&x->gl_obj)); + + /* find all the "dsp" boxes and add them to the graph */ + + for (y = x->gl_list; y; y = y->g_next) + if ((ob = pd_checkobject(&y->g_pd)) && zgetfn(&y->g_pd, dspsym)) + ugen_add(dc, ob); + + /* ... and all dsp interconnections */ + linetraverser_start(&t, x); + while ((oc = linetraverser_next(&t))) + if (obj_issignaloutlet(t.tr_ob, t.tr_outno)) + ugen_connect(dc, t.tr_ob, t.tr_outno, t.tr_ob2, t.tr_inno); + + /* finally, sort them and add them to the DSP chain */ + ugen_done_graph(dc); +} + +static void canvas_dsp(t_canvas *x, t_signal **sp) +{ + canvas_dodsp(x, 0, sp); +} + +int canvas_dspstate; /* for back compatibility with externs - don't use */ + + /* this routine starts DSP for all root canvases. */ +static void canvas_start_dsp(void) +{ + t_canvas *x; + if (THISGUI->i_dspstate) ugen_stop(); + else sys_gui("pdtk_pd_dsp ON\n"); + ugen_start(); + + for (x = pd_getcanvaslist(); x; x = x->gl_next) + canvas_dodsp(x, 1, 0); + + canvas_dspstate = THISGUI->i_dspstate = 1; + if (gensym("pd-dsp-started")->s_thing) + pd_bang(gensym("pd-dsp-started")->s_thing); +} + +static void canvas_stop_dsp(void) +{ + if (THISGUI->i_dspstate) + { + ugen_stop(); + sys_gui("pdtk_pd_dsp OFF\n"); + canvas_dspstate = THISGUI->i_dspstate = 0; + if (gensym("pd-dsp-stopped")->s_thing) + pd_bang(gensym("pd-dsp-stopped")->s_thing); + } +} + + /* DSP can be suspended before, and resumed after, operations which + might affect the DSP chain. For example, we suspend before loading and + resume afterward, so that DSP doesn't get resorted for every DSP object + int the patch. */ + +int canvas_suspend_dsp(void) +{ + int rval = THISGUI->i_dspstate; + if (rval) canvas_stop_dsp(); + return (rval); +} + +void canvas_resume_dsp(int oldstate) +{ + if (oldstate) canvas_start_dsp(); +} + + /* this is equivalent to suspending and resuming in one step. */ +void canvas_update_dsp(void) +{ + if (THISGUI->i_dspstate) canvas_start_dsp(); +} + +/* the "dsp" message to pd starts and stops DSP somputation, and, if +appropriate, also opens and closes the audio device. On exclusive-access +APIs such as ALSA, MMIO, and ASIO (I think) it\s appropriate to close the +audio devices when not using them; but jack behaves better if audio I/O +simply keeps running. This is wasteful of CPU cycles but we do it anyway +and can perhaps regard this is a design flaw in jack that we're working around +here. The function audio_shouldkeepopen() is provided by s_audio.c to tell +us that we should elide the step of closing audio when DSP is turned off.*/ + +void glob_dsp(void *dummy, t_symbol *s, int argc, t_atom *argv) +{ + int newstate; + if (argc) + { + newstate = atom_getfloatarg(0, argc, argv); + if (newstate && !THISGUI->i_dspstate) + { + sys_set_audio_state(1); + canvas_start_dsp(); + } + else if (!newstate && THISGUI->i_dspstate) + { + canvas_stop_dsp(); + if (!audio_shouldkeepopen()) + sys_set_audio_state(0); + } + } + else post("dsp state %d", THISGUI->i_dspstate); +} + +void *canvas_getblock(t_class *blockclass, t_canvas **canvasp) +{ + t_canvas *canvas = *canvasp; + t_gobj *g; + void *ret = 0; + for (g = canvas->gl_list; g; g = g->g_next) + { + if (g->g_pd == blockclass) + ret = g; + } + *canvasp = canvas->gl_owner; + return(ret); +} + +/******************* redrawing data *********************/ + + /* redraw all "scalars" (do this if a drawing command is changed.) + LATER we'll use the "template" information to select which ones we + redraw. Action = 0 for redraw, 1 for draw only, 2 for erase. */ +static void glist_redrawall(t_glist *gl, int action) +{ + t_gobj *g; + int vis = glist_isvisible(gl); + for (g = gl->gl_list; g; g = g->g_next) + { + t_class *cl; + if (vis && g->g_pd == scalar_class) + { + if (action == 1) + { + if (glist_isvisible(gl)) + gobj_vis(g, gl, 1); + } + else if (action == 2) + { + if (glist_isvisible(gl)) + gobj_vis(g, gl, 0); + } + else scalar_redraw((t_scalar *)g, gl); + } + else if (g->g_pd == canvas_class) + glist_redrawall((t_glist *)g, action); + } +} + + /* public interface for above. */ +void canvas_redrawallfortemplate(t_template *template, int action) +{ + t_canvas *x; + /* find all root canvases */ + for (x = pd_getcanvaslist(); x; x = x->gl_next) + glist_redrawall(x, action); +} + + /* find the template defined by a canvas, and redraw all elements + for that */ +void canvas_redrawallfortemplatecanvas(t_canvas *x, int action) +{ + t_gobj *g; + t_template *tmpl; + t_symbol *s1 = gensym("struct"); + for (g = x->gl_list; g; g = g->g_next) + { + t_object *ob = pd_checkobject(&g->g_pd); + t_atom *argv; + if (!ob || ob->te_type != T_OBJECT || + binbuf_getnatom(ob->te_binbuf) < 2) + continue; + argv = binbuf_getvec(ob->te_binbuf); + if (argv[0].a_type != A_SYMBOL || argv[1].a_type != A_SYMBOL + || argv[0].a_w.w_symbol != s1) + continue; + tmpl = template_findbyname(argv[1].a_w.w_symbol); + canvas_redrawallfortemplate(tmpl, action); + } + canvas_redrawallfortemplate(0, action); +} + +/* ------------------------------- declare ------------------------ */ + +/* put "declare" objects in a patch to tell it about the environment in +which objects should be created in this canvas. This includes directories to +search ("-path", "-stdpath") and object libraries to load +("-lib" and "-stdlib"). These must be set before the patch containing +the "declare" object is filled in with its contents; so when the patch is +saved, we throw early messages to the canvas to set the environment +before any objects are created in it. */ + +static t_class *declare_class; + +typedef struct _declare +{ + t_object x_obj; + t_canvas *x_canvas; + int x_useme; +} t_declare; + +static void *declare_new(t_symbol *s, int argc, t_atom *argv) +{ + t_declare *x = (t_declare *)pd_new(declare_class); + x->x_useme = 1; + x->x_canvas = canvas_getcurrent(); + /* LATER update environment and/or load libraries */ + if (!x->x_canvas->gl_loading) + { + /* the object is created by the user (not by loading a patch), + * so update canvas's properties on the fly */ + canvas_declare(x->x_canvas, s, argc, argv); + } + return (x); +} + +static void declare_free(t_declare *x) +{ + x->x_useme = 0; + /* LATER update environment */ +} + +void canvas_savedeclarationsto(t_canvas *x, t_binbuf *b) +{ + t_gobj *y; + + for (y = x->gl_list; y; y = y->g_next) + { + if (pd_class(&y->g_pd) == declare_class) + { + binbuf_addv(b, "s", gensym("#X")); + binbuf_addbinbuf(b, ((t_declare *)y)->x_obj.te_binbuf); + binbuf_addv(b, ";"); + } + /* before 0.47 we also allowed abstractions to write out to the + parent's declarations; now we only allow non-abstraction subpatches + to do so. */ + else if (pd_checkglist(&y->g_pd) && + (pd_compatibilitylevel < 47 || !canvas_isabstraction((t_canvas *)y))) + canvas_savedeclarationsto((t_canvas *)y, b); + } +} + +static void canvas_completepath(char *from, char *to, int bufsize) +{ + if (sys_isabsolutepath(from)) + { + to[0] = '\0'; + } + else if(sys_libdir) + { // if not absolute path, append Pd lib dir + strncpy(to, sys_libdir->s_name, bufsize-10); + to[bufsize-9] = '\0'; + strcat(to, "/extra/"); + } + strncat(to, from, bufsize-strlen(to)); + to[bufsize-1] = '\0'; +} + +/* maybe we should rename check_exists() to sys_access() and move it to s_path */ +#ifdef _WIN32 +static int check_exists(const char*path) +{ + char pathbuf[MAXPDSTRING]; + wchar_t ucs2path[MAXPDSTRING]; + sys_bashfilename(path, pathbuf); + u8_utf8toucs2(ucs2path, MAXPDSTRING, pathbuf, MAXPDSTRING-1); + return (0 == _waccess(ucs2path, 0)); +} +#else +#include +static int check_exists(const char*path) +{ + char pathbuf[MAXPDSTRING]; + sys_bashfilename(path, pathbuf); + return (0 == access(pathbuf, 0)); +} +#endif + +static void canvas_stdpath(t_canvasenvironment *e, char *stdpath) +{ + t_namelist*nl; + char strbuf[MAXPDSTRING]; + if (sys_isabsolutepath(stdpath)) + { + e->ce_path = namelist_append(e->ce_path, stdpath, 0); + return; + } + + /* strip "extra/"-prefix */ + if (!strncmp("extra/", stdpath, 6)) + stdpath+=6; + + /* prefix full pd-path (including extra) */ + canvas_completepath(stdpath, strbuf, MAXPDSTRING); + if (check_exists(strbuf)) + { + e->ce_path = namelist_append(e->ce_path, strbuf, 0); + return; + } + /* check whether the given subdir is in one of the standard-paths */ + for (nl=STUFF->st_staticpath; nl; nl=nl->nl_next) + { + snprintf(strbuf, MAXPDSTRING-1, "%s/%s/", nl->nl_string, stdpath); + strbuf[MAXPDSTRING-1]=0; + if (check_exists(strbuf)) + { + e->ce_path = namelist_append(e->ce_path, strbuf, 0); + return; + } + } +} +static void canvas_stdlib(t_canvasenvironment *e, char *stdlib) +{ + t_namelist*nl; + char strbuf[MAXPDSTRING]; + if (sys_isabsolutepath(stdlib)) + { + sys_load_lib(0, stdlib); + return; + } + + /* strip "extra/"-prefix */ + if (!strncmp("extra/", stdlib, 6)) + stdlib+=6; + + /* prefix full pd-path (including extra) */ + canvas_completepath(stdlib, strbuf, MAXPDSTRING); + if (sys_load_lib(0, strbuf)) + return; + + /* check whether the given library is located in one of the standard-paths */ + for (nl=STUFF->st_staticpath; nl; nl=nl->nl_next) + { + snprintf(strbuf, MAXPDSTRING-1, "%s/%s", nl->nl_string, stdlib); + strbuf[MAXPDSTRING-1]=0; + if (sys_load_lib(0, strbuf)) + return; + } +} + + +void canvas_declare(t_canvas *x, t_symbol *s, int argc, t_atom *argv) +{ + int i; + t_canvasenvironment *e = canvas_getenv(x); +#if 0 + startpost("declare:: %s", s->s_name); + postatom(argc, argv); + endpost(); +#endif + for (i = 0; i < argc; i++) + { + char *flag = atom_getsymbolarg(i, argc, argv)->s_name; + if ((argc > i+1) && !strcmp(flag, "-path")) + { + e->ce_path = namelist_append(e->ce_path, + atom_getsymbolarg(i+1, argc, argv)->s_name, 0); + i++; + } + else if ((argc > i+1) && !strcmp(flag, "-stdpath")) + { + canvas_stdpath(e, atom_getsymbolarg(i+1, argc, argv)->s_name); + i++; + } + else if ((argc > i+1) && !strcmp(flag, "-lib")) + { + sys_load_lib(x, atom_getsymbolarg(i+1, argc, argv)->s_name); + i++; + } + else if ((argc > i+1) && !strcmp(flag, "-stdlib")) + { + canvas_stdlib(e, atom_getsymbolarg(i+1, argc, argv)->s_name); + i++; + } + else post("declare: %s: unknown declaration", flag); + } +} + +typedef struct _canvasopen +{ + const char *name; + const char *ext; + char *dirresult; + char **nameresult; + unsigned int size; + int bin; + int fd; +} t_canvasopen; + +static int canvas_open_iter(const char *path, t_canvasopen *co) +{ + int fd; + if ((fd = sys_trytoopenone(path, co->name, co->ext, + co->dirresult, co->nameresult, co->size, co->bin)) >= 0) + { + co->fd = fd; + return 0; + } + return 1; +} + + /* utility function to read a file, looking first down the canvas's search + path (set with "declare" objects in the patch and recursively in calling + patches), then down the system one. The filename is the concatenation of + "name" and "ext". "Name" may be absolute, or may be relative with + slashes. If anything can be opened, the true directory + ais put in the buffer dirresult (provided by caller), which should + be "size" bytes. The "nameresult" pointer will be set somewhere in + the interior of "dirresult" and will give the file basename (with + slashes trimmed). If "bin" is set a 'binary' open is + attempted, otherwise ASCII (this only matters on Microsoft.) + If "x" is zero, the file is sought in the directory "." or in the + global path.*/ +int canvas_open(t_canvas *x, const char *name, const char *ext, + char *dirresult, char **nameresult, unsigned int size, int bin) +{ + t_namelist *nl, thislist; + int fd = -1; + char listbuf[MAXPDSTRING]; + t_canvas *y; + t_canvasopen co; + + /* first check if "name" is absolute (and if so, try to open) */ + if (sys_open_absolute(name, ext, dirresult, nameresult, size, bin, &fd)) + return (fd); + + /* otherwise "name" is relative; iterate over all the search-paths */ + co.name = name; + co.ext = ext; + co.dirresult = dirresult; + co.nameresult = nameresult; + co.size = size; + co.bin = bin; + co.fd = -1; + + canvas_path_iterate(x, (t_canvas_path_iterator)canvas_open_iter, &co); + + return (co.fd); +} + +/* + * Iterate over all search-paths for calling with the user-supplied + * . The function is called with two arguments: a pathname to try to + * open, and . + */ +int canvas_path_iterate(t_canvas *x, t_canvas_path_iterator fun, + void *user_data) +{ + t_canvas *y = 0; + t_namelist *nl = 0; + int count = 0; + if (!fun) + return 0; + /* iterate through canvas-local paths */ + for (y = x; y; y = y->gl_owner) + if (y->gl_env) + { + char *dir; + dir = canvas_getdir(y)->s_name; + for (nl = y->gl_env->ce_path; nl; nl = nl->nl_next) + { + char realname[MAXPDSTRING]; + if (sys_isabsolutepath(nl->nl_string)) + realname[0] = '\0'; + else + { /* if not absolute path, append Pd lib dir */ + strncpy(realname, dir, MAXPDSTRING); + realname[MAXPDSTRING-3] = 0; + strcat(realname, "/"); + } + strncat(realname, nl->nl_string, MAXPDSTRING-strlen(realname)); + realname[MAXPDSTRING-1] = 0; + if (!fun(realname, user_data)) + return count+1; + count++; + } + } + /* try canvas dir */ + if (!fun((x ? canvas_getdir(x)->s_name : "."), user_data)) + return count+1; + count++; + + /* now iterate through the global paths */ + for (nl = STUFF->st_searchpath; nl; nl = nl->nl_next) + { + if (!fun(nl->nl_string, user_data)) + return count+1; + count++; + } + /* and the default paths */ + if (sys_usestdpath) + for (nl = STUFF->st_staticpath; nl; nl = nl->nl_next) + { + if (!fun(nl->nl_string, user_data)) + return count+1; + count++; + } + + return count; +} + +static void canvas_f(t_canvas *x, t_symbol *s, int argc, t_atom *argv) +{ + static int warned; + t_gobj *g, *g2; + t_object *ob; + if (argc > 1 && !warned) + { + post("** ignoring width or font settings from future Pd version **"); + warned = 1; + } + if (!x->gl_list) + return; + for (g = x->gl_list; (g2 = g->g_next); g = g2) + ; + if ((ob = pd_checkobject(&g->g_pd))) + { + ob->te_width = atom_getfloatarg(0, argc, argv); + if (glist_isvisible(x)) + { + gobj_vis(g, x, 0); + gobj_vis(g, x, 1); + } + } +} + +extern t_class *array_define_class; /* LATER datum class too */ + + /* check if a pd can be treated as a glist - true if we're of any of + the glist classes, which all have 'glist' as the first item in struct */ +t_glist *pd_checkglist(t_pd *x) +{ + if (*x == canvas_class || *x == array_define_class) + return ((t_canvas *)x); + else return (0); +} + +/* ------------------------------- setup routine ------------------------ */ + + /* why are some of these "glist" and others "canvas"? */ +extern void glist_text(t_glist *x, t_symbol *s, int argc, t_atom *argv); +extern void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv); +extern void canvas_bng(t_glist *gl, t_symbol *s, int argc, t_atom *argv); +extern void canvas_toggle(t_glist *gl, t_symbol *s, int argc, t_atom *argv); +extern void canvas_vslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv); +extern void canvas_hslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv); +extern void canvas_vdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv); + /* old version... */ +extern void canvas_hdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv); +extern void canvas_hdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv); + /* new version: */ +extern void canvas_hradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv); +extern void canvas_vradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv); +extern void canvas_vumeter(t_glist *gl, t_symbol *s, int argc, t_atom *argv); +extern void canvas_mycnv(t_glist *gl, t_symbol *s, int argc, t_atom *argv); +extern void canvas_numbox(t_glist *gl, t_symbol *s, int argc, t_atom *argv); +extern void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv); +extern void canvas_floatatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv); +extern void canvas_symbolatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv); +extern void glist_scalar(t_glist *canvas, t_symbol *s, int argc, t_atom *argv); + +void g_graph_setup(void); +void g_editor_setup(void); +void g_readwrite_setup(void); +extern void canvas_properties(t_gobj *z, t_glist *canvas); + +void g_canvas_setup(void) +{ + /* we prevent the user from typing "canvas" in an object box + by sending 0 for a creator function. */ + canvas_class = class_new(gensym("canvas"), 0, + (t_method)canvas_free, sizeof(t_canvas), CLASS_NOINLET, 0); + /* here is the real creator function, invoked in patch files + by sending the "canvas" message to #N, which is bound + to pd_camvasmaker. */ + class_addmethod(pd_canvasmaker, (t_method)canvas_new, gensym("canvas"), + A_GIMME, 0); + class_addmethod(canvas_class, (t_method)canvas_restore, + gensym("restore"), A_GIMME, 0); + class_addmethod(canvas_class, (t_method)canvas_coords, + gensym("coords"), A_GIMME, 0); + +/* -------------------------- objects ----------------------------- */ + class_addmethod(canvas_class, (t_method)canvas_obj, + gensym("obj"), A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_msg, + gensym("msg"), A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_floatatom, + gensym("floatatom"), A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_symbolatom, + gensym("symbolatom"), A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)glist_text, + gensym("text"), A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)glist_glist, gensym("graph"), + A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)glist_scalar, + gensym("scalar"), A_GIMME, A_NULL); + +/* -------------- IEMGUI: button, toggle, slider, etc. ------------ */ + class_addmethod(canvas_class, (t_method)canvas_bng, gensym("bng"), + A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_toggle, gensym("toggle"), + A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_vslider, gensym("vslider"), + A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_hslider, gensym("hslider"), + A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_hdial, gensym("hdial"), + A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_vdial, gensym("vdial"), + A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_hradio, gensym("hradio"), + A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_vradio, gensym("vradio"), + A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_vumeter, gensym("vumeter"), + A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_mycnv, gensym("mycnv"), + A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_numbox, gensym("numbox"), + A_GIMME, A_NULL); + +/* ------------------------ gui stuff --------------------------- */ + class_addmethod(canvas_class, (t_method)canvas_pop, gensym("pop"), + A_DEFFLOAT, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_loadbang, + gensym("loadbang"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_setbounds, + gensym("setbounds"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_relocate, + gensym("relocate"), A_SYMBOL, A_SYMBOL, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_vis, + gensym("vis"), A_FLOAT, A_NULL); + class_addmethod(canvas_class, (t_method)glist_menu_open, + gensym("menu-open"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_map, + gensym("map"), A_FLOAT, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_dirty, + gensym("dirty"), A_FLOAT, A_NULL); + class_setpropertiesfn(canvas_class, canvas_properties); + +/* ---------------------- list handling ------------------------ */ + class_addmethod(canvas_class, (t_method)glist_clear, gensym("clear"), + A_NULL); + +/* ----- subcanvases, which you get by typing "pd" in a box ---- */ + class_addcreator((t_newmethod)subcanvas_new, gensym("pd"), A_DEFSYMBOL, 0); + class_addcreator((t_newmethod)subcanvas_new, gensym("page"), A_DEFSYMBOL, 0); + + class_addmethod(canvas_class, (t_method)canvas_click, + gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(canvas_class, (t_method)canvas_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(canvas_class, (t_method)canvas_rename_method, + gensym("rename"), A_GIMME, 0); + +/*---------------------------- declare ------------------- */ + declare_class = class_new(gensym("declare"), (t_newmethod)declare_new, + (t_method)declare_free, sizeof(t_declare), CLASS_NOINLET, A_GIMME, 0); + class_addmethod(canvas_class, (t_method)canvas_declare, + gensym("declare"), A_GIMME, 0); + +/*--------------- future message to set formatting -------------- */ + class_addmethod(canvas_class, (t_method)canvas_f, + gensym("f"), A_GIMME, 0); +/* -------------- setups from other files for canvas_class ---------------- */ + g_graph_setup(); + g_editor_setup(); + g_readwrite_setup(); +} + + /* functions to add basic gui (e.g., clicking but not editing) to things + based on canvases that aren't editable, like "array define" object */ +void canvas_editor_for_class(t_class *c); +void g_graph_setup_class(t_class *c); +void canvas_readwrite_for_class(t_class *c); + +void canvas_add_for_class(t_class *c) +{ + class_addmethod(c, (t_method)canvas_restore, + gensym("restore"), A_GIMME, 0); + class_addmethod(c, (t_method)canvas_click, + gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(c, (t_method)canvas_dsp, + gensym("dsp"), A_CANT, 0); + class_addmethod(c, (t_method)canvas_map, + gensym("map"), A_FLOAT, A_NULL); + class_addmethod(c, (t_method)canvas_setbounds, + gensym("setbounds"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + canvas_editor_for_class(c); + canvas_readwrite_for_class(c); + /* g_graph_setup_class(c); */ +} + +void g_canvas_newpdinstance( void) +{ + THISGUI = getbytes(sizeof(*THISGUI)); + THISGUI->i_newfilename = THISGUI->i_newdirectory = &s_; + THISGUI->i_newargc = 0; + THISGUI->i_newargv = 0; + THISGUI->i_reloadingabstraction = 0; + THISGUI->i_dspstate = 0; + THISGUI->i_dollarzero = 1000; + g_editor_newpdinstance(); + g_template_newpdinstance(); +} + +void g_canvas_freepdinstance( void) +{ + g_editor_freepdinstance(); + g_template_freepdinstance(); + freebytes(THISGUI, sizeof(*THISGUI)); +} + +EXTERN int pd_getdspstate(void) +{ + return (THISGUI->i_dspstate); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_canvas.h b/ports/camomile/source/LibPd/pure-data/src/g_canvas.h new file mode 100644 index 00000000..19ad9e42 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_canvas.h @@ -0,0 +1,663 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* this file defines the structure for "glists" and related structures and +functions. "Glists" and "canvases" and "graphs" used to be different +structures until being unified in version 0.35. + +A glist occupies its own window if the "gl_havewindow" flag is set. Its +appearance on its "parent", also called "owner", (if it has one) is as a graph +if "gl_isgraph" is set, and otherwise as a text box. + +A glist is "root" if it has no owner, i.e., a document window. In this +case "gl_havewindow" is always set. + +We maintain a list of root windows, so that we can traverse the whole +collection of everything in a Pd process. + +If a glist has a window it may still not be "mapped." Miniaturized +windows aren't mapped, for example, but a window is also not mapped +immediately upon creation. In either case gl_havewindow is true but +gl_mapped is false. + +Closing a non-root window makes it invisible; closing a root destroys it. + +A glist that's just a text object on its parent is always "toplevel." An +embedded glist can switch back and forth to appear as a toplevel by double- +clicking on it. Single-clicking a text box makes the toplevel become visible +and raises the window it's in. + +If a glist shows up as a graph on its parent, the graph is blanked while the +glist has its own window, even if miniaturized. + +*/ + +/* NOTE: this file describes Pd implementation details which may change +in future releases. The public (stable) API is in m_pd.h. */ + +#ifndef G_CANVAS_H +#define G_CANVAS_H + +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) +extern "C" { +#endif + +/* --------------------- geometry ---------------------------- */ +#define IOWIDTH 7 /* width of an inlet/outlet in pixels */ +#define IHEIGHT 3 /* height of an inlet in pixels */ +#define OHEIGHT 3 /* height of an outlet in pixels */ +#define IOMIDDLE ((IOWIDTH-1)/2) +#define GLIST_DEFGRAPHWIDTH 200 +#define GLIST_DEFGRAPHHEIGHT 140 + +/* ----------------------- data ------------------------------- */ + +typedef struct _updateheader +{ + struct _updateheader *upd_next; + unsigned int upd_array:1; /* true if array, false if glist */ + unsigned int upd_queued:1; /* true if we're queued */ +} t_updateheader; + + /* types to support glists grabbing mouse motion or keys from parent */ +typedef void (*t_glistmotionfn)(void *z, t_floatarg dx, t_floatarg dy); +typedef void (*t_glistkeyfn)(void *z, t_floatarg key); + +EXTERN_STRUCT _rtext; +#define t_rtext struct _rtext + +EXTERN_STRUCT _gtemplate; +#define t_gtemplate struct _gtemplate + +EXTERN_STRUCT _guiconnect; +#define t_guiconnect struct _guiconnect + +EXTERN_STRUCT _tscalar; +#define t_tscalar struct _tscalar + +EXTERN_STRUCT _canvasenvironment; +#define t_canvasenvironment struct _canvasenvironment + +EXTERN_STRUCT _fielddesc; +#define t_fielddesc struct _fielddesc + +typedef struct _selection +{ + t_gobj *sel_what; + struct _selection *sel_next; +} t_selection; + + /* this structure is instantiated whenever a glist becomes visible. */ +typedef struct _editor +{ + t_updateheader e_upd; /* update header structure */ + t_selection *e_updlist; /* list of objects to update */ + t_rtext *e_rtext; /* text responder linked list */ + t_selection *e_selection; /* head of the selection list */ + t_rtext *e_textedfor; /* the rtext if any that we are editing */ + t_gobj *e_grab; /* object being "dragged" */ + t_glistmotionfn e_motionfn; /* ... motion callback */ + t_glistkeyfn e_keyfn; /* ... keypress callback */ + t_binbuf *e_connectbuf; /* connections to deleted objects */ + t_binbuf *e_deleted; /* last stuff we deleted */ + t_guiconnect *e_guiconnect; /* GUI connection for filtering messages */ + struct _glist *e_glist; /* glist which owns this */ + int e_xwas; /* xpos on last mousedown or motion event */ + int e_ywas; /* ypos, similarly */ + int e_selectline_index1; /* indices for the selected line if any */ + int e_selectline_outno; /* (only valid if e_selectedline is set) */ + int e_selectline_index2; + int e_selectline_inno; + t_outconnect *e_selectline_tag; + unsigned int e_onmotion: 3; /* action to take on motion */ + unsigned int e_lastmoved: 1; /* one if mouse has moved since click */ + unsigned int e_textdirty: 1; /* one if e_textedfor has changed */ + unsigned int e_selectedline: 1; /* one if a line is selected */ + t_clock *e_clock; /* clock to filter GUI move messages */ + int e_xnew; /* xpos for next move event */ + int e_ynew; /* ypos, similarly */ +} t_editor; + +#define MA_NONE 0 /* e_onmotion: do nothing on mouse motion */ +#define MA_MOVE 1 /* drag the selection around */ +#define MA_CONNECT 2 /* make a connection */ +#define MA_REGION 3 /* selection region */ +#define MA_PASSOUT 4 /* send on to e_grab */ +#define MA_DRAGTEXT 5 /* drag in text editor to alter selection */ +#define MA_RESIZE 6 /* drag to resize */ + +/* editor structure for "garrays". We don't bother to delete and regenerate +this structure when the "garray" becomes invisible or visible, although we +could do so if the structure gets big (like the "editor" above.) */ + +typedef struct _arrayvis +{ + t_updateheader av_upd; /* update header structure */ + t_garray *av_garray; /* owning structure */ +} t_arrayvis; + +/* the t_tick structure describes where to draw x and y "ticks" for a glist */ + +typedef struct _tick /* where to put ticks on x or y axes */ +{ + t_float k_point; /* one point to draw a big tick at */ + t_float k_inc; /* x or y increment per little tick */ + int k_lperb; /* little ticks per big; 0 if no ticks to draw */ +} t_tick; + +/* the t_glist structure, which describes a list of elements that live on an +area of a window. + +*/ + +struct _glist +{ + t_object gl_obj; /* header in case we're a glist */ + t_gobj *gl_list; /* the actual data */ + struct _gstub *gl_stub; /* safe pointer handler */ + int gl_valid; /* incremented when pointers might be stale */ + struct _glist *gl_owner; /* parent glist, supercanvas, or 0 if none */ + int gl_pixwidth; /* width in pixels (on parent, if a graph) */ + int gl_pixheight; + t_float gl_x1; /* bounding rectangle in our own coordinates */ + t_float gl_y1; + t_float gl_x2; + t_float gl_y2; + int gl_screenx1; /* screen coordinates when toplevel */ + int gl_screeny1; + int gl_screenx2; + int gl_screeny2; + int gl_xmargin; /* origin for GOP rectangle */ + int gl_ymargin; + t_tick gl_xtick; /* ticks marking X values */ + int gl_nxlabels; /* number of X coordinate labels */ + t_symbol **gl_xlabel; /* ... an array to hold them */ + t_float gl_xlabely; /* ... and their Y coordinates */ + t_tick gl_ytick; /* same as above for Y ticks and labels */ + int gl_nylabels; + t_symbol **gl_ylabel; + t_float gl_ylabelx; + t_editor *gl_editor; /* editor structure when visible */ + t_symbol *gl_name; /* symbol bound here */ + int gl_font; /* nominal font size in points, e.g., 10 */ + struct _glist *gl_next; /* link in list of toplevels */ + t_canvasenvironment *gl_env; /* root canvases and abstractions only */ + unsigned int gl_havewindow:1; /* true if we own a window */ + unsigned int gl_mapped:1; /* true if, moreover, it's "mapped" */ + unsigned int gl_dirty:1; /* (root canvas only:) patch has changed */ + unsigned int gl_loading:1; /* am now loading from file */ + unsigned int gl_willvis:1; /* make me visible after loading */ + unsigned int gl_edit:1; /* edit mode */ + unsigned int gl_isdeleting:1; /* we're inside glist_delete -- hack! */ + unsigned int gl_goprect:1; /* draw rectangle for graph-on-parent */ + unsigned int gl_isgraph:1; /* show as graph on parent */ + unsigned int gl_hidetext:1; /* hide object-name + args when doing graph on parent */ + unsigned int gl_private:1; /* private flag used in x_scalar.c */ + unsigned int gl_isclone:1; /* exists as part of a clone object */ + int gl_zoom; /* zoom factor (integer zoom-in only) */ +}; + +#define gl_gobj gl_obj.te_g +#define gl_pd gl_gobj.g_pd + +/* a data structure to describe a field in a pure datum */ + +#define DT_FLOAT 0 +#define DT_SYMBOL 1 +#define DT_TEXT 2 +#define DT_ARRAY 3 + +typedef struct _dataslot +{ + int ds_type; + t_symbol *ds_name; + t_symbol *ds_arraytemplate; /* filled in for arrays only */ +} t_dataslot; + +typedef struct _template +{ + t_pd t_pdobj; /* header */ + struct _gtemplate *t_list; /* list of "struct"/gtemplate objects */ + t_symbol *t_sym; /* name */ + int t_n; /* number of dataslots (fields) */ + t_dataslot *t_vec; /* array of dataslots */ +} t_template; + +struct _array +{ + int a_n; /* number of elements */ + int a_elemsize; /* size in bytes; LATER get this from template */ + char *a_vec; /* array of elements */ + t_symbol *a_templatesym; /* template for elements */ + int a_valid; /* protection against stale pointers into array */ + t_gpointer a_gp; /* pointer to scalar or array element we're in */ + t_gstub *a_stub; /* stub for pointing into this array */ +}; + + /* structure for traversing all the connections in a glist */ +typedef struct _linetraverser +{ + t_canvas *tr_x; + t_object *tr_ob; + int tr_nout; + int tr_outno; + t_object *tr_ob2; + t_outlet *tr_outlet; + t_inlet *tr_inlet; + int tr_nin; + int tr_inno; + int tr_x11, tr_y11, tr_x12, tr_y12; + int tr_x21, tr_y21, tr_x22, tr_y22; + int tr_lx1, tr_ly1, tr_lx2, tr_ly2; + t_outconnect *tr_nextoc; + int tr_nextoutno; +} t_linetraverser; + +struct _instancecanvas +{ + struct _instanceeditor *i_editor; + struct _instancetemplate *i_template; + t_symbol *i_newfilename; + t_symbol *i_newdirectory; + int i_newargc; + t_atom *i_newargv; + t_glist *i_reloadingabstraction; + int i_dspstate; + int i_dollarzero; + t_float i_graph_lastxpix, i_graph_lastypix; +}; + +void g_editor_newpdinstance( void); +void g_template_newpdinstance( void); +void g_editor_freepdinstance( void); +void g_template_freepdinstance( void); + +#define THISGUI (pd_this->pd_gui) +#define EDITOR (pd_this->pd_gui->i_editor) +#define TEMPLATE (pd_this->pd_gui->i_template) + +/* function types used to define graphical behavior for gobjs, a bit like X +widgets. We don't use Pd methods because Pd's typechecking can't specify the +types of pointer arguments. Also it's more convenient this way, since +every "patchable" object can just get the "text" behaviors. */ + + /* Call this to get a gobj's bounding rectangle in pixels */ +typedef void (*t_getrectfn)(t_gobj *x, struct _glist *glist, + int *x1, int *y1, int *x2, int *y2); + /* and this to displace a gobj: */ +typedef void (*t_displacefn)(t_gobj *x, struct _glist *glist, int dx, int dy); + /* change color to show selection: */ +typedef void (*t_selectfn)(t_gobj *x, struct _glist *glist, int state); + /* change appearance to show activation/deactivation: */ +typedef void (*t_activatefn)(t_gobj *x, struct _glist *glist, int state); + /* warn a gobj it's about to be deleted */ +typedef void (*t_deletefn)(t_gobj *x, struct _glist *glist); + /* making visible or invisible */ +typedef void (*t_visfn)(t_gobj *x, struct _glist *glist, int flag); + /* field a mouse click (when not in "edit" mode) */ +typedef int (*t_clickfn)(t_gobj *x, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit); + /* ... and later, resizing; getting/setting font or color... */ + +struct _widgetbehavior +{ + t_getrectfn w_getrectfn; + t_displacefn w_displacefn; + t_selectfn w_selectfn; + t_activatefn w_activatefn; + t_deletefn w_deletefn; + t_visfn w_visfn; + t_clickfn w_clickfn; +}; + +/* -------- behaviors for scalars defined by objects in template --------- */ +/* these are set by "drawing commands" in g_template.c which add appearance to +scalars, which live in some other window. If the scalar is just included +in a canvas the "parent" is a misnomer. There is also a text scalar object +which really does draw the scalar on the parent window; see g_scalar.c. */ + +/* note how the click function wants the whole scalar, not the "data", so +doesn't work on array elements... LATER reconsider this */ + + /* bounding rectangle: */ +typedef void (*t_parentgetrectfn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, t_float basex, t_float basey, + int *x1, int *y1, int *x2, int *y2); + /* displace it */ +typedef void (*t_parentdisplacefn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, t_float basex, t_float basey, + int dx, int dy); + /* change color to show selection */ +typedef void (*t_parentselectfn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, t_float basex, t_float basey, + int state); + /* change appearance to show activation/deactivation: */ +typedef void (*t_parentactivatefn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, t_float basex, t_float basey, + int state); + /* making visible or invisible */ +typedef void (*t_parentvisfn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, t_float basex, t_float basey, + int flag); + /* field a mouse click */ +typedef int (*t_parentclickfn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, t_scalar *sc, t_array *ap, + t_float basex, t_float basey, + int xpix, int ypix, int shift, int alt, int dbl, int doit); + +struct _parentwidgetbehavior +{ + t_parentgetrectfn w_parentgetrectfn; + t_parentdisplacefn w_parentdisplacefn; + t_parentselectfn w_parentselectfn; + t_parentactivatefn w_parentactivatefn; + t_parentvisfn w_parentvisfn; + t_parentclickfn w_parentclickfn; +}; + + /* cursor definitions; used as return value for t_parentclickfn */ +#define CURSOR_RUNMODE_NOTHING 0 +#define CURSOR_RUNMODE_CLICKME 1 +#define CURSOR_RUNMODE_THICKEN 2 +#define CURSOR_RUNMODE_ADDPOINT 3 +#define CURSOR_EDITMODE_NOTHING 4 +#define CURSOR_EDITMODE_CONNECT 5 +#define CURSOR_EDITMODE_DISCONNECT 6 +#define CURSOR_EDITMODE_RESIZE 7 +EXTERN void canvas_setcursor(t_glist *x, unsigned int cursornum); + +extern t_canvas *canvas_whichfind; /* last canvas we did a find in */ +extern t_class *vinlet_class, *voutlet_class; +extern int glist_valid; /* incremented when pointers might be stale */ + +#define PLOTSTYLE_POINTS 0 /* plotting styles for arrays */ +#define PLOTSTYLE_POLY 1 +#define PLOTSTYLE_BEZ 2 + +/* ------------------- functions on any gobj ----------------------------- */ +EXTERN void gobj_getrect(t_gobj *x, t_glist *owner, int *x1, int *y1, + int *x2, int *y2); +EXTERN void gobj_displace(t_gobj *x, t_glist *owner, int dx, int dy); +EXTERN void gobj_select(t_gobj *x, t_glist *owner, int state); +EXTERN void gobj_activate(t_gobj *x, t_glist *owner, int state); +EXTERN void gobj_delete(t_gobj *x, t_glist *owner); +EXTERN void gobj_vis(t_gobj *x, t_glist *glist, int flag); +EXTERN int gobj_click(t_gobj *x, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit); +EXTERN void gobj_save(t_gobj *x, t_binbuf *b); +EXTERN void gobj_properties(t_gobj *x, struct _glist *glist); +EXTERN int gobj_shouldvis(t_gobj *x, struct _glist *glist); + +/* -------------------- functions on glists --------------------- */ +EXTERN t_glist *glist_new( void); +EXTERN void glist_init(t_glist *x); +EXTERN void glist_add(t_glist *x, t_gobj *g); + +EXTERN void glist_clear(t_glist *x); +EXTERN t_canvas *glist_getcanvas(t_glist *x); +EXTERN int glist_isselected(t_glist *x, t_gobj *y); +EXTERN void glist_select(t_glist *x, t_gobj *y); +EXTERN void glist_deselect(t_glist *x, t_gobj *y); +EXTERN void glist_noselect(t_glist *x); +EXTERN void glist_selectall(t_glist *x); +EXTERN void glist_delete(t_glist *x, t_gobj *y); +EXTERN void glist_retext(t_glist *x, t_text *y); +EXTERN void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn, + t_glistkeyfn keyfn, int xpos, int ypos); +EXTERN int glist_isvisible(t_glist *x); +EXTERN int glist_istoplevel(t_glist *x); +EXTERN t_glist *glist_findgraph(t_glist *x); +EXTERN int glist_getfont(t_glist *x); +EXTERN int glist_fontwidth(t_glist *x); +EXTERN int glist_fontheight(t_glist *x); +EXTERN int glist_getzoom(t_glist *x); +EXTERN void glist_sort(t_glist *canvas); +EXTERN void glist_read(t_glist *x, t_symbol *filename, t_symbol *format); +EXTERN void glist_mergefile(t_glist *x, t_symbol *filename, t_symbol *format); + +EXTERN t_float glist_pixelstox(t_glist *x, t_float xpix); +EXTERN t_float glist_pixelstoy(t_glist *x, t_float ypix); +EXTERN t_float glist_xtopixels(t_glist *x, t_float xval); +EXTERN t_float glist_ytopixels(t_glist *x, t_float yval); +EXTERN t_float glist_dpixtodx(t_glist *x, t_float dxpix); +EXTERN t_float glist_dpixtody(t_glist *x, t_float dypix); + +EXTERN void glist_getnextxy(t_glist *gl, int *xval, int *yval); +EXTERN void glist_glist(t_glist *g, t_symbol *s, int argc, t_atom *argv); +EXTERN t_glist *glist_addglist(t_glist *g, t_symbol *sym, + t_float x1, t_float y1, t_float x2, t_float y2, + t_float px1, t_float py1, t_float px2, t_float py2); +EXTERN void glist_arraydialog(t_glist *parent, t_symbol *name, + t_floatarg size, t_floatarg saveit, t_floatarg newgraph); +EXTERN t_binbuf *glist_writetobinbuf(t_glist *x, int wholething); +EXTERN int glist_isgraph(t_glist *x); +EXTERN void glist_redraw(t_glist *x); +EXTERN void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime, + char *tag, int x1, int y1, int x2, int y2); +EXTERN void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag); +EXTERN void canvas_create_editor(t_glist *x); +EXTERN void canvas_destroy_editor(t_glist *x); +void canvas_deletelinesforio(t_canvas *x, t_text *text, + t_inlet *inp, t_outlet *outp); +extern int glist_amreloadingabstractions; /* stop GUI changes while reloading */ + +/* -------------------- functions on texts ------------------------- */ +EXTERN void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize); +EXTERN void text_drawborder(t_text *x, t_glist *glist, char *tag, + int width, int height, int firsttime); +EXTERN void text_eraseborder(t_text *x, t_glist *glist, char *tag); +EXTERN int text_xpix(t_text *x, t_glist *glist); +EXTERN int text_ypix(t_text *x, t_glist *glist); +extern const t_widgetbehavior text_widgetbehavior; + +/* -------------------- functions on rtexts ------------------------- */ +#define RTEXT_DOWN 1 +#define RTEXT_DRAG 2 +#define RTEXT_DBL 3 +#define RTEXT_SHIFT 4 + +EXTERN t_rtext *rtext_new(t_glist *glist, t_text *who); +EXTERN t_rtext *glist_findrtext(t_glist *gl, t_text *who); +EXTERN void rtext_draw(t_rtext *x); +EXTERN void rtext_erase(t_rtext *x); +EXTERN t_rtext *rtext_remove(t_rtext *first, t_rtext *x); +EXTERN int rtext_height(t_rtext *x); +EXTERN void rtext_displace(t_rtext *x, int dx, int dy); +EXTERN void rtext_select(t_rtext *x, int state); +EXTERN void rtext_activate(t_rtext *x, int state); +EXTERN void rtext_free(t_rtext *x); +EXTERN void rtext_key(t_rtext *x, int n, t_symbol *s); +EXTERN void rtext_mouse(t_rtext *x, int xval, int yval, int flag); +EXTERN void rtext_retext(t_rtext *x); +EXTERN int rtext_width(t_rtext *x); +EXTERN char *rtext_gettag(t_rtext *x); +EXTERN void rtext_gettext(t_rtext *x, char **buf, int *bufsize); +EXTERN void rtext_getseltext(t_rtext *x, char **buf, int *bufsize); + +/* -------------------- functions on canvases ------------------------ */ +EXTERN t_class *canvas_class; + +EXTERN t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv); +EXTERN t_symbol *canvas_makebindsym(t_symbol *s); +EXTERN void canvas_vistext(t_canvas *x, t_text *y); +EXTERN void canvas_fixlinesfor(t_canvas *x, t_text *text); +EXTERN void canvas_deletelinesfor(t_canvas *x, t_text *text); +EXTERN void canvas_stowconnections(t_canvas *x); +EXTERN void canvas_restoreconnections(t_canvas *x); +EXTERN void canvas_redraw(t_canvas *x); +EXTERN void canvas_closebang(t_canvas *x); +EXTERN void canvas_initbang(t_canvas *x); + +EXTERN t_inlet *canvas_addinlet(t_canvas *x, t_pd *who, t_symbol *sym); +EXTERN void canvas_rminlet(t_canvas *x, t_inlet *ip); +EXTERN t_outlet *canvas_addoutlet(t_canvas *x, t_pd *who, t_symbol *sym); +EXTERN void canvas_rmoutlet(t_canvas *x, t_outlet *op); +EXTERN void canvas_redrawallfortemplate(t_template *tmpl, int action); +EXTERN void canvas_redrawallfortemplatecanvas(t_canvas *x, int action); +EXTERN void canvas_zapallfortemplate(t_canvas *tmpl); +EXTERN void canvas_setusedastemplate(t_canvas *x); +EXTERN void canvas_setcurrent(t_canvas *x); +EXTERN void canvas_unsetcurrent(t_canvas *x); +EXTERN t_symbol *canvas_realizedollar(t_canvas *x, t_symbol *s); +EXTERN t_canvas *canvas_getrootfor(t_canvas *x); +EXTERN void canvas_dirty(t_canvas *x, t_floatarg n); +EXTERN int canvas_getfont(t_canvas *x); +typedef int (*t_canvasapply)(t_canvas *x, t_int x1, t_int x2, t_int x3); + +EXTERN t_int *canvas_recurapply(t_canvas *x, t_canvasapply *fn, + t_int x1, t_int x2, t_int x3); + +EXTERN void canvas_resortinlets(t_canvas *x); +EXTERN void canvas_resortoutlets(t_canvas *x); +EXTERN void canvas_free(t_canvas *x); +EXTERN void canvas_updatewindowlist( void); +EXTERN void canvas_editmode(t_canvas *x, t_floatarg state); +EXTERN int canvas_isabstraction(t_canvas *x); +EXTERN int canvas_istable(t_canvas *x); +EXTERN int canvas_showtext(t_canvas *x); +EXTERN void canvas_vis(t_canvas *x, t_floatarg f); +EXTERN t_canvasenvironment *canvas_getenv(t_canvas *x); +EXTERN void canvas_rename(t_canvas *x, t_symbol *s, t_symbol *dir); +EXTERN void canvas_loadbang(t_canvas *x); +EXTERN int canvas_hitbox(t_canvas *x, t_gobj *y, int xpos, int ypos, + int *x1p, int *y1p, int *x2p, int *y2p); +EXTERN int canvas_setdeleting(t_canvas *x, int flag); + +#define LB_LOAD 0 /* "loadbang" actions - 0 for original meaning */ +#define LB_INIT 1 /* loaded but not yet connected to parent patch */ +#define LB_CLOSE 2 /* about to close */ + + /* Pointer to canvas that was saved necessitating a reload of abstractions + of that name. We use as a flag to stop canvases from being marked "dirty" + if we have to touch them to reload; also suppress window list update. + "clone~" uses this to identify which copy NOT to reload */ +EXTERN t_glist *glist_reloadingabstraction; + +typedef void (*t_undofn)(t_canvas *canvas, void *buf, + int action); /* a function that does UNDO/REDO */ +#define UNDO_FREE 0 /* free current undo/redo buffer */ +#define UNDO_UNDO 1 /* undo */ +#define UNDO_REDO 2 /* redo */ +EXTERN void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf, + const char *name); +EXTERN void canvas_noundo(t_canvas *x); +EXTERN int canvas_getindex(t_canvas *x, t_gobj *y); + +EXTERN void canvas_connect(t_canvas *x, + t_floatarg fwhoout, t_floatarg foutno,t_floatarg fwhoin, t_floatarg finno); +EXTERN void canvas_disconnect(t_canvas *x, + t_float index1, t_float outno, t_float index2, t_float inno); +EXTERN int canvas_isconnected (t_canvas *x, + t_text *ob1, int n1, t_text *ob2, int n2); +EXTERN void canvas_selectinrect(t_canvas *x, int lox, int loy, int hix, int hiy); + +EXTERN t_glist *pd_checkglist(t_pd *x); +typedef int (*t_canvas_path_iterator)(const char *path, void *user_data); +EXTERN int canvas_path_iterate(t_canvas *x, t_canvas_path_iterator fun, + void *user_data); + +/* ---- functions on canvasses as objects --------------------- */ + +EXTERN void canvas_fattenforscalars(t_canvas *x, + int *x1, int *y1, int *x2, int *y2); +EXTERN void canvas_visforscalars(t_canvas *x, t_glist *glist, int vis); +EXTERN int canvas_clicksub(t_canvas *x, int xpix, int ypix, int shift, + int alt, int dbl, int doit); +EXTERN t_glist *canvas_getglistonsuper(void); + +EXTERN void linetraverser_start(t_linetraverser *t, t_canvas *x); +EXTERN t_outconnect *linetraverser_next(t_linetraverser *t); +EXTERN void linetraverser_skipobject(t_linetraverser *t); + +/* --------- functions on garrays (graphical arrays) -------------------- */ + +EXTERN t_template *garray_template(t_garray *x); + +/* -------------------- arrays --------------------- */ +EXTERN t_garray *graph_array(t_glist *gl, t_symbol *s, t_symbol *tmpl, + t_floatarg f, t_floatarg saveit); +EXTERN t_array *array_new(t_symbol *templatesym, t_gpointer *parent); +EXTERN void array_resize(t_array *x, int n); +EXTERN void array_free(t_array *x); +EXTERN void array_redraw(t_array *a, t_glist *glist); +EXTERN void array_resize_and_redraw(t_array *array, t_glist *glist, int n); + +/* --------------------- gpointers and stubs ---------------- */ +EXTERN t_gstub *gstub_new(t_glist *gl, t_array *a); +EXTERN void gstub_cutoff(t_gstub *gs); +EXTERN void gpointer_setglist(t_gpointer *gp, t_glist *glist, t_scalar *x); +EXTERN void gpointer_setarray(t_gpointer *gp, t_array *array, t_word *w); + +/* --------------------- scalars ------------------------- */ +EXTERN void word_init(t_word *wp, t_template *tmpl, t_gpointer *gp); +EXTERN void word_restore(t_word *wp, t_template *tmpl, + int argc, t_atom *argv); +EXTERN t_scalar *scalar_new(t_glist *owner, + t_symbol *templatesym); +EXTERN void word_free(t_word *wp, t_template *tmpl); +EXTERN void scalar_getbasexy(t_scalar *x, t_float *basex, t_float *basey); +EXTERN void scalar_redraw(t_scalar *x, t_glist *glist); +EXTERN void canvas_writescalar(t_symbol *templatesym, t_word *w, t_binbuf *b, + int amarrayelement); +EXTERN int canvas_readscalar(t_glist *x, int natoms, t_atom *vec, + int *p_nextmsg, int selectit); + +/* ------helper routines for "garrays" and "plots" -------------- */ +EXTERN void array_getcoordinate(t_glist *glist, + char *elem, int xonset, int yonset, int wonset, int indx, + t_float basex, t_float basey, t_float xinc, + t_fielddesc *xfielddesc, t_fielddesc *yfielddesc, t_fielddesc *wfielddesc, + t_float *xp, t_float *yp, t_float *wp); + +EXTERN int array_getfields(t_symbol *elemtemplatesym, + t_canvas **elemtemplatecanvasp, + t_template **elemtemplatep, int *elemsizep, + t_fielddesc *xfielddesc, t_fielddesc *yfielddesc, t_fielddesc *wfielddesc, + int *xonsetp, int *yonsetp, int *wonsetp); + +/* --------------------- templates ------------------------- */ +EXTERN t_template *template_new(t_symbol *sym, int argc, t_atom *argv); +EXTERN void template_free(t_template *x); +EXTERN int template_match(t_template *x1, t_template *x2); +EXTERN int template_find_field(t_template *x, t_symbol *name, int *p_onset, + int *p_type, t_symbol **p_arraytype); +EXTERN t_float template_getfloat(t_template *x, t_symbol *fieldname, t_word *wp, + int loud); +EXTERN void template_setfloat(t_template *x, t_symbol *fieldname, t_word *wp, + t_float f, int loud); +EXTERN t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname, + t_word *wp, int loud); +EXTERN void template_setsymbol(t_template *x, t_symbol *fieldname, + t_word *wp, t_symbol *s, int loud); + +EXTERN t_template *gtemplate_get(t_gtemplate *x); +EXTERN t_template *template_findbyname(t_symbol *s); +EXTERN t_canvas *template_findcanvas(t_template *tmpl); +EXTERN void template_notify(t_template *tmpl, + t_symbol *s, int argc, t_atom *argv); + +EXTERN t_float fielddesc_getcoord(t_fielddesc *f, t_template *tmpl, + t_word *wp, int loud); +EXTERN void fielddesc_setcoord(t_fielddesc *f, t_template *tmpl, + t_word *wp, t_float pix, int loud); +EXTERN t_float fielddesc_cvttocoord(t_fielddesc *f, t_float val); +EXTERN t_float fielddesc_cvtfromcoord(t_fielddesc *f, t_float coord); + + +/* ----------------------- guiconnects, g_guiconnect.c --------- */ +EXTERN t_guiconnect *guiconnect_new(t_pd *who, t_symbol *sym); +EXTERN void guiconnect_notarget(t_guiconnect *x, double timedelay); + +/* ------------- IEMGUI routines used in other g_ files ---------------- */ +EXTERN t_symbol *iemgui_raute2dollar(t_symbol *s); +EXTERN t_symbol *iemgui_dollar2raute(t_symbol *s); + +/*------------- g_clone.c ------------- */ +extern t_class *clone_class; + +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) +} +#endif + +#endif // G_CANVAS_H diff --git a/ports/camomile/source/LibPd/pure-data/src/g_clone.c b/ports/camomile/source/LibPd/pure-data/src/g_clone.c new file mode 100644 index 00000000..618afabe --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_clone.c @@ -0,0 +1,464 @@ +#include "m_pd.h" +#include "g_canvas.h" +#include "m_imp.h" +#include + +/* ---------- clone - maintain copies of a patch ----------------- */ +/* OOPS - have to add outlet vector to each copy to disambiguate */ +/* next: feed each instance its serial number */ +/* next next: DSP method */ + + +#ifdef _WIN32 +# include /* MSVC or mingw on windows */ +#elif defined(__linux__) || defined(__APPLE__) +# include /* linux, mac, mingw, cygwin */ +#else +# include /* BSDs for example */ +#endif +#define LIST_NGETBYTE 100 /* bigger that this we use alloc, not alloca */ + +#define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)((n) < LIST_NGETBYTE ? \ + alloca((n) * sizeof(t_atom)) : getbytes((n) * sizeof(t_atom)))) +#define ATOMS_FREEA(x, n) ( \ + ((n) < LIST_NGETBYTE || (freebytes((x), (n) * sizeof(t_atom)), 0))) + +t_class *clone_class; +static t_class *clone_in_class, *clone_out_class; + +typedef struct _copy +{ + t_glist *c_gl; + int c_on; /* DSP running */ +} t_copy; + +typedef struct _in +{ + t_class *i_pd; + struct _clone *i_owner; + int i_signal; + int i_n; +} t_in; + +typedef struct _out +{ + t_class *o_pd; + t_outlet *o_outlet; + int o_signal; + int o_n; +} t_out; + +typedef struct _clone +{ + t_object x_obj; + int x_n; /* number of copies */ + t_copy *x_vec; /* the copies */ + int x_nin; + t_in *x_invec; + int x_nout; + t_out **x_outvec; + t_symbol *x_s; /* name of abstraction */ + int x_argc; /* creation arguments for abstractions */ + t_atom *x_argv; + int x_phase; + int x_startvoice; /* number of first voice, 0 by default */ + int x_suppressvoice; /* suppress voice number as $1 arg */ +} t_clone; + +int clone_match(t_pd *z, t_symbol *name, t_symbol *dir) +{ + t_clone *x = (t_clone *)z; + if (!x->x_n) + return (0); + return (x->x_vec[0].c_gl->gl_name == name && + canvas_getdir(x->x_vec[0].c_gl) == dir); +} + +void obj_sendinlet(t_object *x, int n, t_symbol *s, int argc, t_atom *argv); + +static void clone_in_list(t_in *x, t_symbol *s, int argc, t_atom *argv) +{ + int n; + if (argc < 1 || argv[0].a_type != A_FLOAT) + pd_error(x->i_owner, "clone: no instance number in message"); + else if ((n = argv[0].a_w.w_float - x->i_owner->x_startvoice) < 0 || + n >= x->i_owner->x_n) + pd_error(x->i_owner, "clone: instance number %d out of range", + n + x->i_owner->x_startvoice); + else if (argc > 1 && argv[1].a_type == A_SYMBOL) + obj_sendinlet(&x->i_owner->x_vec[n].c_gl->gl_obj, x->i_n, + argv[1].a_w.w_symbol, argc-2, argv+2); + else obj_sendinlet(&x->i_owner->x_vec[n].c_gl->gl_obj, x->i_n, + &s_list, argc-1, argv+1); +} + +static void clone_in_this(t_in *x, t_symbol *s, int argc, t_atom *argv) +{ + int phase = x->i_owner->x_phase; + if (phase < 0 || phase >= x->i_owner->x_n) + phase = 0; + if (argc <= 0) + return; + else if (argv->a_type == A_SYMBOL) + obj_sendinlet(&x->i_owner->x_vec[phase].c_gl->gl_obj, x->i_n, + argv[0].a_w.w_symbol, argc-1, argv+1); + else obj_sendinlet(&x->i_owner->x_vec[phase].c_gl->gl_obj, x->i_n, + &s_list, argc, argv); +} + +static void clone_in_next(t_in *x, t_symbol *s, int argc, t_atom *argv) +{ + int phase = x->i_owner->x_phase + 1; + if (phase < 0 || phase >= x->i_owner->x_n) + phase = 0; + x->i_owner->x_phase = phase; + clone_in_this(x, s, argc, argv); +} + +static void clone_in_set(t_in *x, t_floatarg f) +{ + int phase = f; + if (phase < 0 || phase >= x->i_owner->x_n) + phase = 0; + x->i_owner->x_phase = phase; +} + +static void clone_in_all(t_in *x, t_symbol *s, int argc, t_atom *argv) +{ + int phasewas = x->i_owner->x_phase, i; + for (i = 0; i < x->i_owner->x_n; i++) + { + x->i_owner->x_phase = i; + clone_in_this(x, s, argc, argv); + } + x->i_owner->x_phase = phasewas; +} + +static void clone_in_vis(t_in *x, t_floatarg fn, t_floatarg vis) +{ + int n = fn - x->i_owner->x_startvoice; + if (n < 0) + n = 0; + else if (n >= x->i_owner->x_n) + n = x->i_owner->x_n - 1; + canvas_vis(x->i_owner->x_vec[n].c_gl, (vis != 0)); +} + +static void clone_out_anything(t_out *x, t_symbol *s, int argc, t_atom *argv) +{ + t_atom *outv, *ap; + int first = + 1 + (s != &s_list && s != &s_float && s != &s_symbol && s != &s_bang), + outc = argc + first; + ATOMS_ALLOCA(outv, outc); + SETFLOAT(outv, x->o_n); + if (first == 2) + SETSYMBOL(outv + 1, s); + memcpy(outv+first, argv, sizeof(t_atom) * argc); + outlet_list(x->o_outlet, 0, outc, outv); + ATOMS_FREEA(outv, outc); +} + +static void clone_free(t_clone *x) +{ + if (x->x_vec) + { + int i; + for (i = 0; i < x->x_n; i++) + { + canvas_closebang(x->x_vec[i].c_gl); + pd_free(&x->x_vec[i].c_gl->gl_pd); + t_freebytes(x->x_outvec[i], + x->x_nout * sizeof(*x->x_outvec[i])); + } + t_freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec)); + t_freebytes(x->x_argv, x->x_argc * sizeof(*x->x_argv)); + t_freebytes(x->x_invec, x->x_nin * sizeof(*x->x_invec)); + t_freebytes(x->x_outvec, x->x_n * sizeof(*x->x_outvec)); + } +} + +static t_canvas *clone_makeone(t_symbol *s, int argc, t_atom *argv) +{ + t_canvas *retval; + pd_this->pd_newest = 0; + typedmess(&pd_objectmaker, s, argc, argv); + if (pd_this->pd_newest == 0) + { + error("clone: can't create subpatch '%s'", + s->s_name); + return (0); + } + if (*pd_this->pd_newest != canvas_class) + { + error("clone: can't clone '%s' because it's not an abstraction", + s->s_name); + pd_free(pd_this->pd_newest); + pd_this->pd_newest = 0; + return (0); + } + retval = (t_canvas *)pd_this->pd_newest; + pd_this->pd_newest = 0; + retval->gl_owner = 0; + retval->gl_isclone = 1; + return (retval); +} + +void clone_setn(t_clone *x, t_floatarg f) +{ + int dspstate = canvas_suspend_dsp(); + int nwas = x->x_n, wantn = f, i, j; + if (wantn < 1) + { + pd_error(x, "can't resize to zero or negative number; setting to 1"); + wantn = 1; + } + if (wantn > nwas) + for (i = nwas; i < wantn; i++) + { + t_canvas *c; + t_out *outvec; + SETFLOAT(x->x_argv, x->x_startvoice + i); + if (!(c = clone_makeone(x->x_s, x->x_argc - x->x_suppressvoice, + x->x_argv + x->x_suppressvoice))) + { + pd_error(x, "clone: couldn't create '%s'", x->x_s->s_name); + goto done; + } + x->x_vec = (t_copy *)t_resizebytes(x->x_vec, i * sizeof(t_copy), + (i+1) * sizeof(t_copy)); + x->x_vec[i].c_gl = c; + x->x_vec[i].c_on = 0; + x->x_outvec = (t_out **)t_resizebytes(x->x_outvec, + i * sizeof(*x->x_outvec), (i+1) * sizeof(*x->x_outvec)); + x->x_outvec[i] = outvec = + (t_out *)getbytes(x->x_nout * sizeof(*outvec)); + for (j = 0; j < x->x_nout; j++) + { + outvec[j].o_pd = clone_out_class; + outvec[j].o_signal = + obj_issignaloutlet(&x->x_vec[0].c_gl->gl_obj, i); + outvec[j].o_n = x->x_startvoice + i; + outvec[j].o_outlet = + x->x_outvec[0][j].o_outlet; + obj_connect(&x->x_vec[i].c_gl->gl_obj, j, + (t_object *)(&outvec[j]), 0); + } + x->x_n++; + } + if (wantn < nwas) + { + for (i = wantn; i < nwas; i++) + { + canvas_closebang(x->x_vec[i].c_gl); + pd_free(&x->x_vec[i].c_gl->gl_pd); + } + x->x_vec = (t_copy *)t_resizebytes(x->x_vec, nwas * sizeof(t_copy), + wantn * sizeof(*x->x_vec)); + x->x_n = wantn; + } +done: + canvas_resume_dsp(dspstate); +} + +static void clone_click(t_clone *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + if (!x->x_n) + return; + canvas_vis(x->x_vec[0].c_gl, 1); +} + +static void clone_loadbang(t_clone *x, t_floatarg f) +{ + int i; + if (f == LB_LOAD) + for (i = 0; i < x->x_n; i++) + canvas_loadbang(x->x_vec[i].c_gl); + else if (f == LB_CLOSE) + for (i = 0; i < x->x_n; i++) + canvas_closebang(x->x_vec[i].c_gl); +} + +void canvas_dodsp(t_canvas *x, int toplevel, t_signal **sp); +t_signal *signal_newfromcontext(int borrowed); +void signal_makereusable(t_signal *sig); + +static void clone_dsp(t_clone *x, t_signal **sp) +{ + int i, j, nin, nout; + t_signal **tempsigs; + if (!x->x_n) + return; + for (i = nin = 0; i < x->x_nin; i++) + if (x->x_invec[i].i_signal) + nin++; + for (i = nout = 0; i < x->x_nout; i++) + if (x->x_outvec[0][i].o_signal) + nout++; + for (j = 0; j < x->x_n; j++) + { + if (obj_ninlets(&x->x_vec[j].c_gl->gl_obj) != x->x_nin || + obj_noutlets(&x->x_vec[j].c_gl->gl_obj) != x->x_nout || + obj_nsiginlets(&x->x_vec[j].c_gl->gl_obj) != nin || + obj_nsigoutlets(&x->x_vec[j].c_gl->gl_obj) != nout) + { + pd_error(x, "clone: can't do DSP until edited copy is saved"); + for (i = 0; i < nout; i++) + dsp_add_zero(sp[nin+i]->s_vec, sp[nin+i]->s_n); + return; + } + } + tempsigs = (t_signal **)alloca((nin + 3 * nout) * sizeof(*tempsigs)); + /* load input signals into signal vector to send subpatches */ + for (i = 0; i < nin; i++) + { + /* we already have one reference "counted" for our presumed + use of this input signal but we must add the others. */ + sp[i]->s_refcount += x->x_n-1; + tempsigs[2 * nout + i] = sp[i]; + } + /* for first copy, write output to first nout temp sigs */ + for (i = 0; i < nout; i++) + tempsigs[i] = tempsigs[2 * nout + nin + i] = signal_newfromcontext(1); + canvas_dodsp(x->x_vec[0].c_gl, 0, tempsigs + 2*nout); + /* for remaining copies, write to second nout temp sigs */ + for (j = 1; j < x->x_n; j++) + { + for (i = 0; i < nout; i++) + tempsigs[nout+i] = tempsigs[2 * nout + nin + i] = + signal_newfromcontext(1); + canvas_dodsp(x->x_vec[j].c_gl, 0, tempsigs + 2*nout); + for (i = 0; i < nout; i++) + { + dsp_add_plus(tempsigs[nout + i]->s_vec, tempsigs[i]->s_vec, + tempsigs[i]->s_vec, tempsigs[i]->s_n); + signal_makereusable(tempsigs[nout + i]); + } + } + /* copy to output signsls */ + for (i = 0; i < nout; i++) + { + dsp_add_copy(tempsigs[i]->s_vec, sp[nin+i]->s_vec, tempsigs[i]->s_n); + signal_makereusable(tempsigs[i]); + } +} + +static void *clone_new(t_symbol *s, int argc, t_atom *argv) +{ + t_clone *x = (t_clone *)pd_new(clone_class); + t_canvas *c; + int wantn, dspstate, i; + t_out *outvec; + x->x_invec = 0; + x->x_outvec = 0; + x->x_startvoice = 0; + x->x_suppressvoice = 0; + if (argc == 0) + { + x->x_vec = 0; + x->x_n = 0; + return (x); + } + dspstate = canvas_suspend_dsp(); + while (argc > 0 && argv[0].a_type == A_SYMBOL && + argv[0].a_w.w_symbol->s_name[0] == '-') + { + if (!strcmp(argv[0].a_w.w_symbol->s_name, "-s") && argc > 1 && + argv[1].a_type == A_FLOAT) + { + x->x_startvoice = argv[1].a_w.w_float; + argc -= 2; argv += 2; + } + else if (!strcmp(argv[0].a_w.w_symbol->s_name, "-x")) + x->x_suppressvoice = 1, argc--, argv++; + else goto usage; + } + if (argc >= 2 && (wantn = atom_getfloatarg(0, argc, argv)) >= 0 + && argv[1].a_type == A_SYMBOL) + x->x_s = argv[1].a_w.w_symbol; + else if (argc >= 2 && (wantn = atom_getfloatarg(1, argc, argv)) >= 0 + && argv[0].a_type == A_SYMBOL) + x->x_s = argv[0].a_w.w_symbol; + else goto usage; + /* store a copy of the argmuents with an extra space (argc+1) for + supplying an instance number, which we'll bash as we go. */ + x->x_argc = argc - 1; + x->x_argv = getbytes(x->x_argc * sizeof(*x->x_argv)); + memcpy(x->x_argv, argv+1, x->x_argc * sizeof(*x->x_argv)); + SETFLOAT(x->x_argv, x->x_startvoice); + if (!(c = clone_makeone(x->x_s, x->x_argc - x->x_suppressvoice, + x->x_argv + x->x_suppressvoice))) + goto fail; + x->x_vec = (t_copy *)getbytes(sizeof(*x->x_vec)); + x->x_vec[0].c_gl = c; + x->x_n = 1; + x->x_nin = obj_ninlets(&x->x_vec[0].c_gl->gl_obj); + x->x_invec = (t_in *)getbytes(x->x_nin * sizeof(*x->x_invec)); + for (i = 0; i < x->x_nin; i++) + { + x->x_invec[i].i_pd = clone_in_class; + x->x_invec[i].i_owner = x; + x->x_invec[i].i_signal = + obj_issignalinlet(&x->x_vec[0].c_gl->gl_obj, i); + x->x_invec[i].i_n = i; + if (x->x_invec[i].i_signal) + signalinlet_new(&x->x_obj, 0); + else inlet_new(&x->x_obj, &x->x_invec[i].i_pd, 0, 0); + } + x->x_nout = obj_noutlets(&x->x_vec[0].c_gl->gl_obj); + x->x_outvec = (t_out **)getbytes(sizeof(*x->x_outvec)); + x->x_outvec[0] = outvec = + (t_out *)getbytes(x->x_nout * sizeof(*outvec)); + for (i = 0; i < x->x_nout; i++) + { + outvec[i].o_pd = clone_out_class; + outvec[i].o_signal = + obj_issignaloutlet(&x->x_vec[0].c_gl->gl_obj, i); + outvec[i].o_n = x->x_startvoice; + outvec[i].o_outlet = + outlet_new(&x->x_obj, (outvec[i].o_signal ? &s_signal : 0)); + obj_connect(&x->x_vec[0].c_gl->gl_obj, i, + (t_object *)(&outvec[i]), 0); + } + clone_setn(x, (t_floatarg)(wantn)); + x->x_phase = wantn-1; + canvas_resume_dsp(dspstate); + return (x); +usage: + error("usage: clone [-s starting-number] [arguments]"); +fail: + freebytes(x, sizeof(t_clone)); + canvas_resume_dsp(dspstate); + return (0); +} + +void clone_setup(void) +{ + clone_class = class_new(gensym("clone"), (t_newmethod)clone_new, + (t_method)clone_free, sizeof(t_clone), CLASS_NOINLET, A_GIMME, 0); + class_addmethod(clone_class, (t_method)clone_click, gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(clone_class, (t_method)clone_loadbang, gensym("loadbang"), + A_FLOAT, 0); + class_addmethod(clone_class, (t_method)clone_dsp, + gensym("dsp"), A_CANT, 0); + + clone_in_class = class_new(gensym("clone-inlet"), 0, 0, + sizeof(t_in), CLASS_PD, 0); + class_addmethod(clone_in_class, (t_method)clone_in_next, gensym("next"), + A_GIMME, 0); + class_addmethod(clone_in_class, (t_method)clone_in_this, gensym("this"), + A_GIMME, 0); + class_addmethod(clone_in_class, (t_method)clone_in_set, gensym("set"), + A_FLOAT, 0); + class_addmethod(clone_in_class, (t_method)clone_in_all, gensym("all"), + A_GIMME, 0); + class_addmethod(clone_in_class, (t_method)clone_in_vis, gensym("vis"), + A_FLOAT, A_FLOAT, 0); + class_addlist(clone_in_class, (t_method)clone_in_list); + + clone_out_class = class_new(gensym("clone-outlet"), 0, 0, + sizeof(t_in), CLASS_PD, 0); + class_addanything(clone_out_class, (t_method)clone_out_anything); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_editor.c b/ports/camomile/source/LibPd/pure-data/src/g_editor.c new file mode 100644 index 00000000..0a29f018 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_editor.c @@ -0,0 +1,2990 @@ +/* Copyright (c) 1997-2001 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include +#include +#include "m_pd.h" +#include "m_imp.h" +#include "s_stuff.h" +#include "g_canvas.h" +#include "s_utf8.h" /*-- moo --*/ +#include +#ifdef _MSC_VER /* This is only for Microsoft's compiler, not cygwin, e.g. */ +#define snprintf _snprintf +#endif + +struct _instanceeditor +{ + t_binbuf *copy_binbuf; + char *canvas_textcopybuf; + int canvas_textcopybufsize; + t_undofn canvas_undo_fn; /* current undo function if any */ + int canvas_undo_whatnext; /* whether we can now UNDO or REDO */ + void *canvas_undo_buf; /* data private to the undo function */ + t_canvas *canvas_undo_canvas; /* which canvas we can undo on */ + const char *canvas_undo_name; + int canvas_undo_already_set_move; + double canvas_upclicktime; + int canvas_upx, canvas_upy; + int canvas_find_index, canvas_find_wholeword; + t_binbuf *canvas_findbuf; + int paste_onset; + t_canvas *paste_canvas; + t_glist *canvas_last_glist; + int canvas_last_glist_x, canvas_last_glist_y; + t_canvas *canvas_cursorcanvaswas; + unsigned int canvas_cursorwas; +}; + +void glist_readfrombinbuf(t_glist *x, t_binbuf *b, char *filename, + int selectem); + +/* ------------------ forward declarations --------------- */ +static void canvas_doclear(t_canvas *x); +static void glist_setlastxy(t_glist *gl, int xval, int yval); +static void glist_donewloadbangs(t_glist *x); +static t_binbuf *canvas_docopy(t_canvas *x); +static void canvas_dopaste(t_canvas *x, t_binbuf *b); +static void canvas_paste(t_canvas *x); +static void canvas_clearline(t_canvas *x); +static t_glist *glist_finddirty(t_glist *x); +static void canvas_zoom(t_canvas *x, t_floatarg zoom); + +/* ---------------- generic widget behavior ------------------------- */ + +void gobj_getrect(t_gobj *x, t_glist *glist, int *x1, int *y1, + int *x2, int *y2) +{ + if (x->g_pd->c_wb && x->g_pd->c_wb->w_getrectfn) + (*x->g_pd->c_wb->w_getrectfn)(x, glist, x1, y1, x2, y2); + else *x1 = *y1 = 0, *x2 = *y2 = 10; +} + +void gobj_displace(t_gobj *x, t_glist *glist, int dx, int dy) +{ + if (x->g_pd->c_wb && x->g_pd->c_wb->w_displacefn) + (*x->g_pd->c_wb->w_displacefn)(x, glist, dx, dy); +} + + /* here we add an extra check whether we're mapped, because some + editing moves are carried out on invisible windows (notably, re-creating + abstractions when one is saved). Should any other widget finctions also + be doing this? */ +void gobj_select(t_gobj *x, t_glist *glist, int state) +{ + if (glist->gl_mapped && x->g_pd->c_wb && x->g_pd->c_wb->w_selectfn) + (*x->g_pd->c_wb->w_selectfn)(x, glist, state); +} + +void gobj_activate(t_gobj *x, t_glist *glist, int state) +{ + if (x->g_pd->c_wb && x->g_pd->c_wb->w_activatefn) + (*x->g_pd->c_wb->w_activatefn)(x, glist, state); +} + +void gobj_delete(t_gobj *x, t_glist *glist) +{ + if (x->g_pd->c_wb && x->g_pd->c_wb->w_deletefn) + (*x->g_pd->c_wb->w_deletefn)(x, glist); +} + +int gobj_shouldvis(t_gobj *x, struct _glist *glist) +{ + t_object *ob; + /* if our parent is a graph, and if that graph itself isn't + visible, then we aren't either. */ + if (!glist->gl_havewindow && glist->gl_isgraph && glist->gl_owner + && !gobj_shouldvis(&glist->gl_gobj, glist->gl_owner)) + return (0); + /* if we're graphing-on-parent and the object falls outside the + graph rectangle, don't draw it. */ + if (!glist->gl_havewindow && glist->gl_isgraph && glist->gl_goprect && + glist->gl_owner) + { + int x1, y1, x2, y2, gx1, gy1, gx2, gy2, m; + /* for some reason the bounds check on arrays and scalars + don't seem to apply here. Perhaps this was in order to allow + arrays to reach outside their containers? I no longer understand + this. */ + if (pd_class(&x->g_pd) == scalar_class + || pd_class(&x->g_pd) == garray_class) + return (1); + gobj_getrect(&glist->gl_gobj, glist->gl_owner, &x1, &y1, &x2, &y2); + if (x1 > x2) + m = x1, x1 = x2, x2 = m; + if (y1 > y2) + m = y1, y1 = y2, y2 = m; + gobj_getrect(x, glist, &gx1, &gy1, &gx2, &gy2); + /* post("graph %d %d %d %d, %s %d %d %d %d", + x1, x2, y1, y2, class_gethelpname(x->g_pd), gx1, gx2, gy1, gy2); */ + if (gx1 < x1 || gx1 > x2 || gx2 < x1 || gx2 > x2 || + gy1 < y1 || gy1 > y2 || gy2 < y1 || gy2 > y2) + return (0); + } + if ((ob = pd_checkobject(&x->g_pd))) + { + /* return true if the text box should be drawn. We don't show text + boxes inside graphs---except comments, if we're doing the new + (goprect) style. */ + return (glist->gl_havewindow || + (ob->te_pd != canvas_class && + ob->te_pd->c_wb != &text_widgetbehavior) || + (ob->te_pd == canvas_class && (((t_glist *)ob)->gl_isgraph)) || + (glist->gl_goprect && (ob->te_type == T_TEXT))); + } + else return (1); +} + +void gobj_vis(t_gobj *x, struct _glist *glist, int flag) +{ + if (x->g_pd->c_wb && x->g_pd->c_wb->w_visfn && gobj_shouldvis(x, glist)) + (*x->g_pd->c_wb->w_visfn)(x, glist, flag); +} + +int gobj_click(t_gobj *x, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + if (x->g_pd->c_wb && x->g_pd->c_wb->w_clickfn) + return ((*x->g_pd->c_wb->w_clickfn)(x, + glist, xpix, ypix, shift, alt, dbl, doit)); + else return (0); +} + +/* ------------------------ managing the selection ----------------- */ + +void glist_selectline(t_glist *x, t_outconnect *oc, int index1, + int outno, int index2, int inno) +{ + if (x->gl_editor) + { + glist_noselect(x); + x->gl_editor->e_selectedline = 1; + x->gl_editor->e_selectline_index1 = index1; + x->gl_editor->e_selectline_outno = outno; + x->gl_editor->e_selectline_index2 = index2; + x->gl_editor->e_selectline_inno = inno; + x->gl_editor->e_selectline_tag = oc; + sys_vgui(".x%lx.c itemconfigure l%lx -fill blue\n", + x, x->gl_editor->e_selectline_tag); + } +} + +void glist_deselectline(t_glist *x) +{ + if (x->gl_editor) + { + x->gl_editor->e_selectedline = 0; + sys_vgui(".x%lx.c itemconfigure l%lx -fill black\n", + x, x->gl_editor->e_selectline_tag); + } +} + +int glist_isselected(t_glist *x, t_gobj *y) +{ + if (x->gl_editor) + { + t_selection *sel; + for (sel = x->gl_editor->e_selection; sel; sel = sel->sel_next) + if (sel->sel_what == y) return (1); + } + return (0); +} + + /* call this for unselected objects only */ +void glist_select(t_glist *x, t_gobj *y) +{ + if (x->gl_editor) + { + t_selection *sel = (t_selection *)getbytes(sizeof(*sel)); + if (x->gl_editor->e_selectedline) + glist_deselectline(x); + /* LATER #ifdef out the following check */ + if (glist_isselected(x, y)) bug("glist_select"); + sel->sel_next = x->gl_editor->e_selection; + sel->sel_what = y; + x->gl_editor->e_selection = sel; + gobj_select(y, x, 1); + } +} + + /* recursively deselect everything in a gobj "g", if it happens to be + a glist, in preparation for deselecting g itself in glist_dselect() */ +static void glist_checkanddeselectall(t_glist *gl, t_gobj *g) +{ + t_glist *gl2; + t_gobj *g2; + if (pd_class(&g->g_pd) != canvas_class) + return; + gl2 = (t_glist *)g; + for (g2 = gl2->gl_list; g2; g2 = g2->g_next) + glist_checkanddeselectall(gl2, g2); + glist_noselect(gl2); +} + + /* call this for selected objects only */ +void glist_deselect(t_glist *x, t_gobj *y) +{ + int fixdsp = 0; + if (x->gl_editor) + { + t_selection *sel, *sel2; + t_rtext *z = 0; + if (!glist_isselected(x, y)) bug("glist_deselect"); + if (x->gl_editor->e_textedfor) + { + t_rtext *fuddy = glist_findrtext(x, (t_text *)y); + if (x->gl_editor->e_textedfor == fuddy) + { + if (x->gl_editor->e_textdirty) + { + z = fuddy; + canvas_stowconnections(glist_getcanvas(x)); + glist_checkanddeselectall(x, y); + } + gobj_activate(y, x, 0); + } + if (zgetfn(&y->g_pd, gensym("dsp"))) + fixdsp = canvas_suspend_dsp(); + } + if ((sel = x->gl_editor->e_selection)->sel_what == y) + { + x->gl_editor->e_selection = x->gl_editor->e_selection->sel_next; + gobj_select(sel->sel_what, x, 0); + freebytes(sel, sizeof(*sel)); + } + else + { + for (sel = x->gl_editor->e_selection; (sel2 = sel->sel_next); + sel = sel2) + { + if (sel2->sel_what == y) + { + sel->sel_next = sel2->sel_next; + gobj_select(sel2->sel_what, x, 0); + freebytes(sel2, sizeof(*sel2)); + break; + } + } + } + if (z) + { + char *buf; + int bufsize; + + rtext_gettext(z, &buf, &bufsize); + text_setto((t_text *)y, x, buf, bufsize); + canvas_fixlinesfor(x, (t_text *)y); + x->gl_editor->e_textedfor = 0; + } + if (fixdsp) + canvas_resume_dsp(1); + } +} + +void glist_noselect(t_glist *x) +{ + if (x->gl_editor) + { + while (x->gl_editor->e_selection) + glist_deselect(x, x->gl_editor->e_selection->sel_what); + if (x->gl_editor->e_selectedline) + glist_deselectline(x); + } +} + +void glist_selectall(t_glist *x) +{ + if (x->gl_editor) + { + glist_noselect(x); + if (x->gl_list) + { + t_selection *sel = (t_selection *)getbytes(sizeof(*sel)); + t_gobj *y = x->gl_list; + x->gl_editor->e_selection = sel; + sel->sel_what = y; + gobj_select(y, x, 1); + while ((y = y->g_next)) + { + t_selection *sel2 = (t_selection *)getbytes(sizeof(*sel2)); + sel->sel_next = sel2; + sel = sel2; + sel->sel_what = y; + gobj_select(y, x, 1); + } + sel->sel_next = 0; + } + } +} + + /* get the index of a gobj in a glist. If y is zero, return the + total number of objects. */ +int glist_getindex(t_glist *x, t_gobj *y) +{ + t_gobj *y2; + int indx; + + for (y2 = x->gl_list, indx = 0; y2 && y2 != y; y2 = y2->g_next) + indx++; + return (indx); +} + + /* get the index of the object, among selected items, if "selected" + is set; otherwise, among unselected ones. If y is zero, just + counts the selected or unselected objects. */ +int glist_selectionindex(t_glist *x, t_gobj *y, int selected) +{ + t_gobj *y2; + int indx; + + for (y2 = x->gl_list, indx = 0; y2 && y2 != y; y2 = y2->g_next) + if (selected == glist_isselected(x, y2)) + indx++; + return (indx); +} + +static t_gobj *glist_nth(t_glist *x, int n) +{ + t_gobj *y; + int indx; + for (y = x->gl_list, indx = 0; y; y = y->g_next, indx++) + if (indx == n) + return (y); + return (0); +} + +/* ------------------- support for undo/redo -------------------------- */ + +void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf, + const char *name) +{ + int hadone = 0; + /* blow away the old undo information. In one special case the + old undo info is re-used; if so we shouldn't free it here. */ + if (EDITOR->canvas_undo_fn && EDITOR->canvas_undo_buf && (buf != EDITOR->canvas_undo_buf)) + { + (*EDITOR->canvas_undo_fn)(EDITOR->canvas_undo_canvas, EDITOR->canvas_undo_buf, UNDO_FREE); + hadone = 1; + } + EDITOR->canvas_undo_canvas = x; + EDITOR->canvas_undo_fn = undofn; + EDITOR->canvas_undo_buf = buf; + EDITOR->canvas_undo_whatnext = UNDO_UNDO; + EDITOR->canvas_undo_name = name; + if (x && glist_isvisible(x) && glist_istoplevel(x)) + /* enable undo in menu */ + sys_vgui("pdtk_undomenu .x%lx %s no\n", x, name); + else if (hadone) + sys_vgui("pdtk_undomenu nobody no no\n"); +} + + /* clear undo if it happens to be for the canvas x. + (but if x is 0, clear it regardless of who owns it.) */ +void canvas_noundo(t_canvas *x) +{ + if (!x || (x == EDITOR->canvas_undo_canvas)) + canvas_setundo(0, 0, 0, "foo"); +} + +static void canvas_undo(t_canvas *x) +{ + int dspwas = canvas_suspend_dsp(); + if (x != EDITOR->canvas_undo_canvas) + bug("canvas_undo 1"); + else if (EDITOR->canvas_undo_whatnext != UNDO_UNDO) + bug("canvas_undo 2"); + else + { + /* post("undo"); */ + (*EDITOR->canvas_undo_fn)(EDITOR->canvas_undo_canvas, + EDITOR->canvas_undo_buf, UNDO_UNDO); + /* enable redo in menu */ + if (glist_isvisible(x) && glist_istoplevel(x)) + sys_vgui("pdtk_undomenu .x%lx no %s\n", x, + EDITOR->canvas_undo_name); + EDITOR->canvas_undo_whatnext = UNDO_REDO; + } + canvas_resume_dsp(dspwas); +} + +static void canvas_redo(t_canvas *x) +{ + int dspwas = canvas_suspend_dsp(); + if (x != EDITOR->canvas_undo_canvas) + bug("canvas_undo 1"); + else if (EDITOR->canvas_undo_whatnext != UNDO_REDO) + bug("canvas_undo 2"); + else + { + /* post("redo"); */ + (*EDITOR->canvas_undo_fn)(EDITOR->canvas_undo_canvas, + EDITOR->canvas_undo_buf, UNDO_REDO); + /* enable undo in menu */ + if (glist_isvisible(x) && glist_istoplevel(x)) + sys_vgui("pdtk_undomenu .x%lx %s no\n", x, + EDITOR->canvas_undo_name); + EDITOR->canvas_undo_whatnext = UNDO_UNDO; + } + canvas_resume_dsp(dspwas); +} + +/* ------- specific undo methods: 1. connect and disconnect -------- */ + +typedef struct _undo_connect +{ + int u_index1; + int u_outletno; + int u_index2; + int u_inletno; +} t_undo_connect; + +static void *canvas_undo_set_disconnect(t_canvas *x, + int index1, int outno, int index2, int inno) +{ + t_undo_connect *buf = (t_undo_connect *)getbytes(sizeof(*buf)); + buf->u_index1 = index1; + buf->u_outletno = outno; + buf->u_index2 = index2; + buf->u_inletno = inno; + return (buf); +} + +void canvas_disconnect(t_canvas *x, + t_float index1, t_float outno, t_float index2, t_float inno) +{ + t_linetraverser t; + t_outconnect *oc; + linetraverser_start(&t, x); + while ((oc = linetraverser_next(&t))) + { + int srcno = canvas_getindex(x, &t.tr_ob->ob_g); + int sinkno = canvas_getindex(x, &t.tr_ob2->ob_g); + if (srcno == index1 && t.tr_outno == outno && + sinkno == index2 && t.tr_inno == inno) + { + sys_vgui(".x%lx.c delete l%lx\n", x, oc); + obj_disconnect(t.tr_ob, t.tr_outno, t.tr_ob2, t.tr_inno); + break; + } + } +} + +static void canvas_undo_disconnect(t_canvas *x, void *z, int action) +{ + t_undo_connect *buf = z; + if (action == UNDO_UNDO) + { + canvas_connect(x, buf->u_index1, buf->u_outletno, + buf->u_index2, buf->u_inletno); + } + else if (action == UNDO_REDO) + { + canvas_disconnect(x, buf->u_index1, buf->u_outletno, + buf->u_index2, buf->u_inletno); + } + else if (action == UNDO_FREE) + t_freebytes(buf, sizeof(*buf)); +} + + /* connect just calls disconnect actions backward... */ +static void *canvas_undo_set_connect(t_canvas *x, + int index1, int outno, int index2, int inno) +{ + return (canvas_undo_set_disconnect(x, index1, outno, index2, inno)); +} + +static void canvas_undo_connect(t_canvas *x, void *z, int action) +{ + int myaction; + if (action == UNDO_UNDO) + myaction = UNDO_REDO; + else if (action == UNDO_REDO) + myaction = UNDO_UNDO; + else myaction = action; + canvas_undo_disconnect(x, z, myaction); +} + +/* ---------- ... 2. cut, clear, and typing into objects: -------- */ + +#define UCUT_CUT 1 /* operation was a cut */ +#define UCUT_CLEAR 2 /* .. a clear */ +#define UCUT_TEXT 3 /* text typed into a box */ + +typedef struct _undo_cut +{ + t_binbuf *u_objectbuf; /* the object cleared or typed into */ + t_binbuf *u_reconnectbuf; /* connections into and out of object */ + t_binbuf *u_redotextbuf; /* buffer to paste back for redo if TEXT */ + int u_mode; /* from flags above */ +} t_undo_cut; + +static void *canvas_undo_set_cut(t_canvas *x, int mode) +{ + t_undo_cut *buf; + t_gobj *y; + t_linetraverser t; + t_outconnect *oc; + int nnotsel= glist_selectionindex(x, 0, 0); + buf = (t_undo_cut *)getbytes(sizeof(*buf)); + buf->u_mode = mode; + buf->u_redotextbuf = 0; + + /* store connections into/out of the selection */ + buf->u_reconnectbuf = binbuf_new(); + linetraverser_start(&t, x); + while ((oc = linetraverser_next(&t))) + { + int issel1 = glist_isselected(x, &t.tr_ob->ob_g); + int issel2 = glist_isselected(x, &t.tr_ob2->ob_g); + if (issel1 != issel2) + { + binbuf_addv(buf->u_reconnectbuf, "ssiiii;", + gensym("#X"), gensym("connect"), + (issel1 ? nnotsel : 0) + + glist_selectionindex(x, &t.tr_ob->ob_g, issel1), + t.tr_outno, + (issel2 ? nnotsel : 0) + + glist_selectionindex(x, &t.tr_ob2->ob_g, issel2), + t.tr_inno); + } + } + if (mode == UCUT_TEXT) + { + buf->u_objectbuf = canvas_docopy(x); + } + else if (mode == UCUT_CUT) + { + buf->u_objectbuf = 0; + } + else if (mode == UCUT_CLEAR) + { + buf->u_objectbuf = canvas_docopy(x); + } + return (buf); +} + +static void canvas_undo_cut(t_canvas *x, void *z, int action) +{ + t_undo_cut *buf = z; + int mode = buf->u_mode; + t_pd *boundx = s__X.s_thing; + if (action == UNDO_UNDO) + { + if (mode == UCUT_CUT) + canvas_dopaste(x, EDITOR->copy_binbuf); + else if (mode == UCUT_CLEAR) + canvas_dopaste(x, buf->u_objectbuf); + else if (mode == UCUT_TEXT) + { + t_gobj *y1, *y2; + glist_noselect(x); + for (y1 = x->gl_list; (y2 = y1->g_next); y1 = y2) + ; + if (y1) + { + if (!buf->u_redotextbuf) + { + glist_noselect(x); + glist_select(x, y1); + buf->u_redotextbuf = canvas_docopy(x); + glist_noselect(x); + } + glist_delete(x, y1); + } + canvas_dopaste(x, buf->u_objectbuf); + } + s__X.s_thing = &x->gl_pd; + binbuf_eval(buf->u_reconnectbuf, 0, 0, 0); + s__X.s_thing = boundx; + } + else if (action == UNDO_REDO) + { + if (mode == UCUT_CUT || mode == UCUT_CLEAR) + canvas_doclear(x); + else if (mode == UCUT_TEXT) + { + t_gobj *y1, *y2; + for (y1 = x->gl_list; (y2 = y1->g_next); y1 = y2) + ; + if (y1) + glist_delete(x, y1); + canvas_dopaste(x, buf->u_redotextbuf); + s__X.s_thing = &x->gl_pd; + binbuf_eval(buf->u_reconnectbuf, 0, 0, 0); + s__X.s_thing = boundx; + } + } + else if (action == UNDO_FREE) + { + if (buf->u_objectbuf) + binbuf_free(buf->u_objectbuf); + if (buf->u_reconnectbuf) + binbuf_free(buf->u_reconnectbuf); + if (buf->u_redotextbuf) + binbuf_free(buf->u_redotextbuf); + t_freebytes(buf, sizeof(*buf)); + } +} + +/* --------- 3. motion, including "tidy up" and stretching ----------- */ + +typedef struct _undo_move_elem +{ + int e_index; + int e_xpix; + int e_ypix; +} t_undo_move_elem; + +typedef struct _undo_move +{ + t_undo_move_elem *u_vec; + int u_n; +} t_undo_move; + +static void *canvas_undo_set_move(t_canvas *x, int selected) +{ + int x1, y1, x2, y2, i, indx; + t_gobj *y; + t_undo_move *buf = (t_undo_move *)getbytes(sizeof(*buf)); + buf->u_n = selected ? glist_selectionindex(x, 0, 1) : glist_getindex(x, 0); + buf->u_vec = (t_undo_move_elem *)getbytes(sizeof(*buf->u_vec) * + (selected ? glist_selectionindex(x, 0, 1) : glist_getindex(x, 0))); + if (selected) + { + for (y = x->gl_list, i = indx = 0; y; y = y->g_next, indx++) + if (glist_isselected(x, y)) + { + gobj_getrect(y, x, &x1, &y1, &x2, &y2); + buf->u_vec[i].e_index = indx; + buf->u_vec[i].e_xpix = x1; + buf->u_vec[i].e_ypix = y1; + i++; + } + } + else + { + for (y = x->gl_list, indx = 0; y; y = y->g_next, indx++) + { + gobj_getrect(y, x, &x1, &y1, &x2, &y2); + buf->u_vec[indx].e_index = indx; + buf->u_vec[indx].e_xpix = x1; + buf->u_vec[indx].e_ypix = y1; + } + } + EDITOR->canvas_undo_already_set_move = 1; + return (buf); +} + +static void canvas_undo_move(t_canvas *x, void *z, int action) +{ + t_undo_move *buf = z; + if (action == UNDO_UNDO || action == UNDO_REDO) + { + int i; + for (i = 0; i < buf->u_n; i++) + { + int x1, y1, x2, y2, newx, newy; + t_gobj *y; + newx = buf->u_vec[i].e_xpix; + newy = buf->u_vec[i].e_ypix; + y = glist_nth(x, buf->u_vec[i].e_index); + if (y) + { + gobj_getrect(y, x, &x1, &y1, &x2, &y2); + gobj_displace(y, x, newx-x1, newy - y1); + buf->u_vec[i].e_xpix = x1; + buf->u_vec[i].e_ypix = y1; + } + } + } + else if (action == UNDO_FREE) + { + t_freebytes(buf->u_vec, buf->u_n * sizeof(*buf->u_vec)); + t_freebytes(buf, sizeof(*buf)); + } +} + +/* --------- 4. paste (also duplicate) ----------- */ + +typedef struct _undo_paste +{ + int u_index; /* index of first object pasted */ +} t_undo_paste; + +static void *canvas_undo_set_paste(t_canvas *x) +{ + t_undo_paste *buf = (t_undo_paste *)getbytes(sizeof(*buf)); + buf->u_index = glist_getindex(x, 0); + return (buf); +} + +static void canvas_undo_paste(t_canvas *x, void *z, int action) +{ + t_undo_paste *buf = z; + if (action == UNDO_UNDO) + { + t_gobj *y; + glist_noselect(x); + for (y = glist_nth(x, buf->u_index); y; y = y->g_next) + glist_select(x, y); + canvas_doclear(x); + } + else if (action == UNDO_REDO) + { + t_selection *sel; + canvas_dopaste(x, EDITOR->copy_binbuf); + /* if it was "duplicate" have to re-enact the displacement. */ + if (EDITOR->canvas_undo_name && EDITOR->canvas_undo_name[0] == 'd') + for (sel = x->gl_editor->e_selection; sel; sel = sel->sel_next) + gobj_displace(sel->sel_what, x, 10, 10); + } +else if (action == UNDO_FREE) + t_freebytes(buf, sizeof(*buf)); +} + +int clone_match(t_pd *z, t_symbol *name, t_symbol *dir); + + /* recursively check for abstractions to reload as result of a save. + Don't reload the one we just saved ("except") though. */ + /* LATER try to do the same trick for externs. */ +static void glist_doreload(t_glist *gl, t_symbol *name, t_symbol *dir, + t_gobj *except) +{ + t_gobj *g; + int i, nobj = glist_getindex(gl, 0); /* number of objects */ + int hadwindow = (gl->gl_editor != 0); + for (g = gl->gl_list, i = 0; g && i < nobj; i++) + { + /* remake the object if it's an abstraction that appears to have + been loaded from the file we just saved */ + int remakeit = (g != except && pd_class(&g->g_pd) == canvas_class && + canvas_isabstraction((t_canvas *)g) && + ((t_canvas *)g)->gl_name == name && + canvas_getdir((t_canvas *)g) == dir); + /* also remake it if it's a "clone" with that name */ + if (pd_class(&g->g_pd) == clone_class && + clone_match(&g->g_pd, name, dir)) + { + /* LATER try not to remake the one that equals "except" */ + remakeit = 1; + } + if (remakeit) + { + /* we're going to remake the object, so "g" will go stale. + Get its index here, and afterward restore g. Also, the + replacement will be at the end of the list, so we don't + do g = g->g_next in this case. */ + int j = glist_getindex(gl, g); + if (!gl->gl_editor) + canvas_vis(gl, 1); + if (!gl->gl_editor) + bug("editor"); + glist_noselect(gl); + glist_select(gl, g); + canvas_setundo(gl, canvas_undo_cut, + canvas_undo_set_cut(gl, UCUT_CLEAR), "clear"); + canvas_doclear(gl); + canvas_undo(gl); + glist_noselect(gl); + g = glist_nth(gl, j); + } + else + { + if (g != except && pd_class(&g->g_pd) == canvas_class) + glist_doreload((t_canvas *)g, name, dir, except); + g = g->g_next; + } + } + if (!hadwindow && gl->gl_editor) + canvas_vis(glist_getcanvas(gl), 0); +} + + /* call canvas_doreload on everyone */ +void canvas_reload(t_symbol *name, t_symbol *dir, t_glist *except) +{ + t_canvas *x; + int dspwas = canvas_suspend_dsp(); + THISGUI->i_reloadingabstraction = except; + /* find all root canvases */ + for (x = pd_getcanvaslist(); x; x = x->gl_next) + glist_doreload(x, name, dir, &except->gl_gobj); + THISGUI->i_reloadingabstraction = 0; + canvas_resume_dsp(dspwas); +} + +/* ------------------------ event handling ------------------------ */ + +static const char *cursorlist[] = { + "$cursor_runmode_nothing", + "$cursor_runmode_clickme", + "$cursor_runmode_thicken", + "$cursor_runmode_addpoint", + "$cursor_editmode_nothing", + "$cursor_editmode_connect", + "$cursor_editmode_disconnect", + "$cursor_editmode_resize" +}; + +void canvas_setcursor(t_canvas *x, unsigned int cursornum) +{ + if (cursornum >= sizeof(cursorlist)/sizeof *cursorlist) + { + bug("canvas_setcursor"); + return; + } + if (EDITOR->canvas_cursorcanvaswas != x || + EDITOR->canvas_cursorwas != cursornum) + { + sys_vgui(".x%lx configure -cursor %s\n", x, cursorlist[cursornum]); + EDITOR->canvas_cursorcanvaswas = x; + EDITOR->canvas_cursorwas = cursornum; + } +} + + /* check if a point lies in a gobj. */ +int canvas_hitbox(t_canvas *x, t_gobj *y, int xpos, int ypos, + int *x1p, int *y1p, int *x2p, int *y2p) +{ + int x1, y1, x2, y2; + t_text *ob; + if (!gobj_shouldvis(y, x)) + return (0); + gobj_getrect(y, x, &x1, &y1, &x2, &y2); + if (xpos >= x1 && xpos <= x2 && ypos >= y1 && ypos <= y2) + { + *x1p = x1; + *y1p = y1; + *x2p = x2; + *y2p = y2; + return (1); + } + else return (0); +} + + /* find the last gobj, if any, containing the point. */ +static t_gobj *canvas_findhitbox(t_canvas *x, int xpos, int ypos, + int *x1p, int *y1p, int *x2p, int *y2p) +{ + t_gobj *y, *rval = 0; + int x1, y1, x2, y2; + *x1p = -0x7fffffff; + for (y = x->gl_list; y; y = y->g_next) + { + if (canvas_hitbox(x, y, xpos, ypos, &x1, &y1, &x2, &y2) + && (x1 > *x1p)) + *x1p = x1, *y1p = y1, *x2p = x2, *y2p = y2, rval = y; + } + /* if there are at least two selected objects, we'd prefer + to find a selected one (never mind which) to the one we got. */ + if (x->gl_editor && x->gl_editor->e_selection && + x->gl_editor->e_selection->sel_next && !glist_isselected(x, y)) + { + t_selection *sel; + for (sel = x->gl_editor->e_selection; sel; sel = sel->sel_next) + if (canvas_hitbox(x, sel->sel_what, xpos, ypos, &x1, &y1, &x2, &y2)) + *x1p = x1, *y1p = y1, *x2p = x2, *y2p = y2, + rval = sel->sel_what; + } + return (rval); +} + + /* right-clicking on a canvas object pops up a menu. */ +static void canvas_rightclick(t_canvas *x, int xpos, int ypos, t_gobj *y) +{ + int canprop, canopen; + canprop = (!y || (y && class_getpropertiesfn(pd_class(&y->g_pd)))); + canopen = (y && zgetfn(&y->g_pd, gensym("menu-open"))); + sys_vgui("pdtk_canvas_popup .x%lx %d %d %d %d\n", + x, xpos, ypos, canprop, canopen); +} + +/* ---- editors -- perhaps this and "vis" should go to g_editor.c ------- */ + +static t_editor *editor_new(t_glist *owner) +{ + char buf[40]; + t_editor *x = (t_editor *)getbytes(sizeof(*x)); + x->e_connectbuf = binbuf_new(); + x->e_deleted = binbuf_new(); + x->e_glist = owner; + sprintf(buf, ".x%lx", (t_int)owner); + x->e_guiconnect = guiconnect_new(&owner->gl_pd, gensym(buf)); + x->e_clock = 0; + return (x); +} + +static void editor_free(t_editor *x, t_glist *y) +{ + glist_noselect(y); + guiconnect_notarget(x->e_guiconnect, 1000); + binbuf_free(x->e_connectbuf); + binbuf_free(x->e_deleted); + if (x->e_clock) + clock_free(x->e_clock); + freebytes((void *)x, sizeof(*x)); +} + + /* recursively create or destroy all editors of a glist and its + sub-glists, as long as they aren't toplevels. */ +void canvas_create_editor(t_glist *x) +{ + t_gobj *y; + t_object *ob; + if (!x->gl_editor) + { + x->gl_editor = editor_new(x); + for (y = x->gl_list; y; y = y->g_next) + if ((ob = pd_checkobject(&y->g_pd))) + rtext_new(x, ob); + } +} + +void canvas_destroy_editor(t_glist *x) +{ + t_gobj *y; + t_object *ob; + glist_noselect(x); + if (x->gl_editor) + { + t_rtext *rtext; + while ((rtext = x->gl_editor->e_rtext)) + rtext_free(rtext); + editor_free(x->gl_editor, x); + x->gl_editor = 0; + } +} + +void canvas_reflecttitle(t_canvas *x); +void canvas_map(t_canvas *x, t_floatarg f); + + /* we call this when we want the window to become visible, mapped, and + in front of all windows; or with "f" zero, when we want to get rid of + the window. */ +void canvas_vis(t_canvas *x, t_floatarg f) +{ + char buf[30]; + int flag = (f != 0); + if (flag) + { + /* If a subpatch/abstraction has GOP/gl_isgraph set, then it will have + * a gl_editor already, if its not, it will not have a gl_editor. + * canvas_create_editor(x) checks if a gl_editor is already created, + * so its ok to run it on a canvas that already has a gl_editor. */ + if (x->gl_editor && x->gl_havewindow) + { /* just put us in front */ + sys_vgui("pdtk_canvas_raise .x%lx\n", x); + } + else + { + char cbuf[MAXPDSTRING]; + int cbuflen; + t_canvas *c = x; + canvas_create_editor(x); + sys_vgui("pdtk_canvas_new .x%lx %d %d +%d+%d %d\n", x, + (int)(x->gl_screenx2 - x->gl_screenx1), + (int)(x->gl_screeny2 - x->gl_screeny1), + (int)(x->gl_screenx1), (int)(x->gl_screeny1), + x->gl_edit); + snprintf(cbuf, MAXPDSTRING - 2, "pdtk_canvas_setparents .x%lx", + (unsigned long)c); + while (c->gl_owner) { + c = c->gl_owner; + cbuflen = (int)strlen(cbuf); + snprintf(cbuf + cbuflen, + MAXPDSTRING - cbuflen - 2,/* leave 2 for "\n\0" */ + " .x%lx", (unsigned long)c); + } + strcat(cbuf, "\n"); + sys_gui(cbuf); + canvas_reflecttitle(x); + x->gl_havewindow = 1; + canvas_updatewindowlist(); + } + } + else /* make invisible */ + { + int i; + t_canvas *x2; + if (!x->gl_havewindow) + { + /* bug workaround -- a graph in a visible patch gets "invised" + when the patch is closed, and must lose the editor here. It's + probably not the natural place to do this. Other cases like + subpatches fall here too but don'd need the editor freed, so + we check if it exists. */ + if (x->gl_editor) + canvas_destroy_editor(x); + return; + } + glist_noselect(x); + if (glist_isvisible(x)) + canvas_map(x, 0); + canvas_destroy_editor(x); + sys_vgui("destroy .x%lx\n", x); + for (i = 1, x2 = x; x2; x2 = x2->gl_next, i++) + ; + /* if we're a graph on our parent, and if the parent exists + and is visible, show ourselves on parent. */ + if (glist_isgraph(x) && x->gl_owner) + { + t_glist *gl2 = x->gl_owner; + if (glist_isvisible(gl2)) + gobj_vis(&x->gl_gobj, gl2, 0); + x->gl_havewindow = 0; + if (glist_isvisible(gl2) && !gl2->gl_isdeleting) + { + /* make sure zoom level matches parent, ie. after an open + subpatch's zoom level was changed before being closed */ + if(x->gl_zoom != gl2->gl_zoom) + canvas_zoom(x, gl2->gl_zoom); + gobj_vis(&x->gl_gobj, gl2, 1); + } + } + else x->gl_havewindow = 0; + canvas_updatewindowlist(); + } +} + + /* set a canvas up as a graph-on-parent. Set reasonable defaults for + any missing parameters and redraw things if necessary. */ +void canvas_setgraph(t_glist *x, int flag, int nogoprect) +{ + if (!flag && glist_isgraph(x)) + { + if (x->gl_owner && !x->gl_loading && glist_isvisible(x->gl_owner)) + gobj_vis(&x->gl_gobj, x->gl_owner, 0); + x->gl_isgraph = x->gl_hidetext = 0; + if (x->gl_owner && !x->gl_loading && glist_isvisible(x->gl_owner)) + { + gobj_vis(&x->gl_gobj, x->gl_owner, 1); + canvas_fixlinesfor(x->gl_owner, &x->gl_obj); + } + } + else if (flag) + { + if (x->gl_pixwidth <= 0) + x->gl_pixwidth = GLIST_DEFGRAPHWIDTH; + + if (x->gl_pixheight <= 0) + x->gl_pixheight = GLIST_DEFGRAPHHEIGHT; + + if (x->gl_owner && !x->gl_loading && glist_isvisible(x->gl_owner)) + gobj_vis(&x->gl_gobj, x->gl_owner, 0); + x->gl_isgraph = 1; + x->gl_hidetext = !(!(flag&2)); + x->gl_goprect = !nogoprect; + if (glist_isvisible(x) && x->gl_goprect) + glist_redraw(x); + if (x->gl_owner && !x->gl_loading && glist_isvisible(x->gl_owner)) + { + gobj_vis(&x->gl_gobj, x->gl_owner, 1); + canvas_fixlinesfor(x->gl_owner, &x->gl_obj); + } + } +} + +void garray_properties(t_garray *x); + + /* tell GUI to create a properties dialog on the canvas. We tell + the user the negative of the "pixel" y scale to make it appear to grow + naturally upward, whereas pixels grow downward. */ +void canvas_properties(t_gobj*z, t_glist*unused) +{ + t_glist *x = (t_glist*)z; + t_gobj *y; + char graphbuf[200]; + if (glist_isgraph(x) != 0) + sprintf(graphbuf, + "pdtk_canvas_dialog %%s %g %g %d %g %g %g %g %d %d %d %d\n", + 0., 0., + glist_isgraph(x) ,//1, + x->gl_x1, x->gl_y1, x->gl_x2, x->gl_y2, + (int)x->gl_pixwidth/x->gl_zoom, (int)x->gl_pixheight/x->gl_zoom, + (int)x->gl_xmargin/x->gl_zoom, (int)x->gl_ymargin/x->gl_zoom); + else sprintf(graphbuf, + "pdtk_canvas_dialog %%s %g %g %d %g %g %g %g %d %d %d %d\n", + glist_dpixtodx(x, 1), -glist_dpixtody(x, 1), + 0, + 0., -1., 1., 1., + (int)x->gl_pixwidth/x->gl_zoom, (int)x->gl_pixheight/x->gl_zoom, + (int)x->gl_xmargin/x->gl_zoom, (int)x->gl_ymargin/x->gl_zoom); + gfxstub_new(&x->gl_pd, x, graphbuf); + /* if any arrays are in the graph, put out their dialogs too */ + for (y = x->gl_list; y; y = y->g_next) + if (pd_class(&y->g_pd) == garray_class) + garray_properties((t_garray *)y); +} + + /* called from the gui when "OK" is selected on the canvas properties + dialog. Again we negate "y" scale. */ +static void canvas_donecanvasdialog(t_glist *x, + t_symbol *s, int argc, t_atom *argv) +{ + + + t_float xperpix, yperpix, x1, y1, x2, y2, xpix, ypix, xmargin, ymargin; + int graphme, redraw = 0, fromgui; + + xperpix = atom_getfloatarg(0, argc, argv); + yperpix = atom_getfloatarg(1, argc, argv); + graphme = (int)(atom_getfloatarg(2, argc, argv)); + x1 = atom_getfloatarg(3, argc, argv); + y1 = atom_getfloatarg(4, argc, argv); + x2 = atom_getfloatarg(5, argc, argv); + y2 = atom_getfloatarg(6, argc, argv); + xpix = atom_getfloatarg(7, argc, argv); + ypix = atom_getfloatarg(8, argc, argv); + xmargin = atom_getfloatarg(9, argc, argv); + ymargin = atom_getfloatarg(10, argc, argv); + fromgui = atom_getfloatarg(11, argc, argv); + /* hack - if graphme is 2 (meaning, not GOP but hide the text anyhow), + perhaps we're happier with 0. This is only checked if this is really + being called, as intended, from the GUI. For compatibility with old + patches that reverse-engineered donecanvasdialog to modify patch + parameters, we leave the buggy behavior in when there's no "fromgui" + argument supplied. */ + if (fromgui && (!(graphme & 1))) + graphme = 0; + x->gl_pixwidth = xpix * x->gl_zoom; + x->gl_pixheight = ypix * x->gl_zoom; + x->gl_xmargin = xmargin * x->gl_zoom; + x->gl_ymargin = ymargin * x->gl_zoom; + + yperpix = -yperpix; + if (xperpix == 0) + xperpix = 1; + if (yperpix == 0) + yperpix = 1; + + if (graphme) + { + if (x1 != x2) + x->gl_x1 = x1, x->gl_x2 = x2; + else x->gl_x1 = 0, x->gl_x2 = 1; + if (y1 != y2) + x->gl_y1 = y1, x->gl_y2 = y2; + else x->gl_y1 = 0, x->gl_y2 = 1; + } + else + { + if (xperpix != glist_dpixtodx(x, 1) || yperpix != glist_dpixtody(x, 1)) + redraw = 1; + if (xperpix > 0) + { + x->gl_x1 = 0; + x->gl_x2 = xperpix; + } + else + { + x->gl_x1 = -xperpix * (x->gl_screenx2 - x->gl_screenx1); + x->gl_x2 = x->gl_x1 + xperpix; + } + if (yperpix > 0) + { + x->gl_y1 = 0; + x->gl_y2 = yperpix; + } + else + { + x->gl_y1 = -yperpix * (x->gl_screeny2 - x->gl_screeny1); + x->gl_y2 = x->gl_y1 + yperpix; + } + } + /* LATER avoid doing 2 redraws here (possibly one inside setgraph) */ + canvas_setgraph(x, graphme, 0); + canvas_dirty(x, 1); + if (x->gl_havewindow) + canvas_redraw(x); + else if (glist_isvisible(x->gl_owner)) + { + gobj_vis(&x->gl_gobj, x->gl_owner, 0); + gobj_vis(&x->gl_gobj, x->gl_owner, 1); + } +} + + /* called from the gui when a popup menu comes back with "properties," + "open," or "help." */ +static void canvas_done_popup(t_canvas *x, t_float which, + t_float xpos, t_float ypos) +{ + char pathbuf[MAXPDSTRING], namebuf[MAXPDSTRING], *basenamep; + t_gobj *y; + for (y = x->gl_list; y; y = y->g_next) + { + int x1, y1, x2, y2; + if (canvas_hitbox(x, y, xpos, ypos, &x1, &y1, &x2, &y2)) + { + if (which == 0) /* properties */ + { + if (!class_getpropertiesfn(pd_class(&y->g_pd))) + continue; + (*class_getpropertiesfn(pd_class(&y->g_pd)))(y, x); + return; + } + else if (which == 1) /* open */ + { + if (!zgetfn(&y->g_pd, gensym("menu-open"))) + continue; + vmess(&y->g_pd, gensym("menu-open"), ""); + return; + } + else /* help */ + { + char *dir; + if (pd_class(&y->g_pd) == canvas_class && + canvas_isabstraction((t_canvas *)y)) + { + t_object *ob = (t_object *)y; + int ac = binbuf_getnatom(ob->te_binbuf); + t_atom *av = binbuf_getvec(ob->te_binbuf); + if (ac < 1) + return; + atom_string(av, namebuf, MAXPDSTRING); + + /* strip dir from name : */ + basenamep = strrchr(namebuf, '/'); +#ifdef _WIN32 + if (!basenamep) + basenamep = strrchr(namebuf, '\\'); +#endif + if (!basenamep) + basenamep = namebuf; + else basenamep++; /* strip last '/' */ + + dir = canvas_getdir((t_canvas *)y)->s_name; + } + else + { + strncpy(namebuf, class_gethelpname(pd_class(&y->g_pd)), + MAXPDSTRING-1); + namebuf[MAXPDSTRING-1] = 0; + dir = class_gethelpdir(pd_class(&y->g_pd)); + basenamep = namebuf; + } + if (strlen(namebuf) < 4 || + strcmp(namebuf + strlen(namebuf) - 3, ".pd")) + strcat(namebuf, ".pd"); + open_via_helppath(basenamep, dir); + return; + } + } + } + if (which == 0) + canvas_properties(&x->gl_gobj, 0); + else if (which == 2) + open_via_helppath("intro.pd", canvas_getdir((t_canvas *)x)->s_name); +} + +#define NOMOD 0 +#define SHIFTMOD 1 +#define CTRLMOD 2 +#define ALTMOD 4 +#define RIGHTCLICK 8 + +#define DCLICKINTERVAL 0.25 + + /* mouse click */ +void canvas_doclick(t_canvas *x, int xpos, int ypos, int which, + int mod, int doit) +{ + t_gobj *y; + int shiftmod, runmode, altmod, doublemod = 0, rightclick; + int x1=0, y1=0, x2=0, y2=0, clickreturned = 0; + + if (!x->gl_editor) + { + bug("editor"); + return; + } + + shiftmod = (mod & SHIFTMOD); + runmode = ((mod & CTRLMOD) || (!x->gl_edit)); + altmod = (mod & ALTMOD); + rightclick = (mod & RIGHTCLICK); + + EDITOR->canvas_undo_already_set_move = 0; + + /* if keyboard was grabbed, notify grabber and cancel the grab */ + if (doit && x->gl_editor->e_grab && x->gl_editor->e_keyfn) + { + (* x->gl_editor->e_keyfn) (x->gl_editor->e_grab, 0); + glist_grab(x, 0, 0, 0, 0, 0); + } + + if (doit && !runmode && xpos == EDITOR->canvas_upx && + ypos == EDITOR->canvas_upy && + sys_getrealtime() - EDITOR->canvas_upclicktime < DCLICKINTERVAL) + doublemod = 1; + x->gl_editor->e_lastmoved = 0; + if (doit) + { + x->gl_editor->e_grab = 0; + x->gl_editor->e_onmotion = MA_NONE; + } + /* post("click %d %d %d %d", xpos, ypos, which, mod); */ + + if (x->gl_editor->e_onmotion != MA_NONE) + return; + + x->gl_editor->e_xwas = xpos; + x->gl_editor->e_ywas = ypos; + + if (runmode && !rightclick) + { + for (y = x->gl_list; y; y = y->g_next) + { + /* check if the object wants to be clicked */ + if (canvas_hitbox(x, y, xpos, ypos, &x1, &y1, &x2, &y2) + && (clickreturned = gobj_click(y, x, xpos, ypos, + shiftmod, ((mod & CTRLMOD) && (!x->gl_edit)) || altmod, + 0, doit))) + break; + } + if (!doit) + { + if (y) + canvas_setcursor(x, clickreturned); + else canvas_setcursor(x, CURSOR_RUNMODE_NOTHING); + } + return; + } + /* if not a runmode left click, fall here. */ + if ((y = canvas_findhitbox(x, xpos, ypos, &x1, &y1, &x2, &y2))) + { + t_object *ob = pd_checkobject(&y->g_pd); + /* check you're in the rectangle */ + ob = pd_checkobject(&y->g_pd); + if (rightclick) + canvas_rightclick(x, xpos, ypos, y); + else if (shiftmod) + { + if (doit) + { + t_rtext *rt; + if (ob && (rt = x->gl_editor->e_textedfor) && + rt == glist_findrtext(x, ob)) + { + rtext_mouse(rt, xpos - x1, ypos - y1, RTEXT_SHIFT); + x->gl_editor->e_onmotion = MA_DRAGTEXT; + x->gl_editor->e_xwas = x1; + x->gl_editor->e_ywas = y1; + } + else + { + if (glist_isselected(x, y)) + glist_deselect(x, y); + else glist_select(x, y); + } + } + } + else + { + int noutlet; + /* resize? only for "true" text boxes or canvases*/ + if (ob && !x->gl_editor->e_selection && + (ob->te_pd->c_wb == &text_widgetbehavior || + pd_checkglist(&ob->te_pd)) && + xpos >= x2-4 && ypos < y2-4) + { + if (doit) + { + if (!glist_isselected(x, y)) + { + glist_noselect(x); + glist_select(x, y); + } + x->gl_editor->e_onmotion = MA_RESIZE; + x->gl_editor->e_xwas = x1; + x->gl_editor->e_ywas = y1; + x->gl_editor->e_xnew = xpos; + x->gl_editor->e_ynew = ypos; + } + else canvas_setcursor(x, CURSOR_EDITMODE_RESIZE); + } + /* look for an outlet */ + else if (ob && (noutlet = obj_noutlets(ob)) && + ypos >= y2 - (OHEIGHT*x->gl_zoom) + x->gl_zoom) + { + int width = x2 - x1; + int iow = IOWIDTH * x->gl_zoom; + int nout1 = (noutlet > 1 ? noutlet - 1 : 1); + int closest = ((xpos-x1) * (nout1) + width/2)/width; + int hotspot = x1 + + (width - iow) * closest / (nout1); + if (closest < noutlet && + xpos >= (hotspot - x->gl_zoom) && + xpos <= hotspot + (iow + x->gl_zoom)) + { + if (doit) + { + int issignal = obj_issignaloutlet(ob, closest); + x->gl_editor->e_onmotion = MA_CONNECT; + x->gl_editor->e_xwas = xpos; + x->gl_editor->e_ywas = ypos; + sys_vgui( + ".x%lx.c create line %d %d %d %d -width %d -tags x\n", + x, xpos, ypos, xpos, ypos, + (issignal ? 2 : 1) * x->gl_zoom); + } + else canvas_setcursor(x, CURSOR_EDITMODE_CONNECT); + } + else if (doit) + goto nooutletafterall; + else canvas_setcursor(x, CURSOR_EDITMODE_NOTHING); + } + /* not in an outlet; select and move */ + else if (doit) + { + t_rtext *rt; + /* check if the box is being text edited */ + nooutletafterall: + if (ob && (rt = x->gl_editor->e_textedfor) && + rt == glist_findrtext(x, ob)) + { + rtext_mouse(rt, xpos - x1, ypos - y1, + (doublemod ? RTEXT_DBL : RTEXT_DOWN)); + x->gl_editor->e_onmotion = MA_DRAGTEXT; + x->gl_editor->e_xwas = x1; + x->gl_editor->e_ywas = y1; + } + else + { + /* otherwise select and drag to displace */ + if (!glist_isselected(x, y)) + { + glist_noselect(x); + glist_select(x, y); + } + x->gl_editor->e_onmotion = MA_MOVE; + } + } + else canvas_setcursor(x, CURSOR_EDITMODE_NOTHING); + } + return; + } + /* if right click doesn't hit any boxes, call rightclick + routine anyway */ + if (rightclick) + canvas_rightclick(x, xpos, ypos, 0); + + /* if not an editing action, and if we didn't hit a + box, set cursor and return */ + if (runmode || rightclick) + { + canvas_setcursor(x, CURSOR_RUNMODE_NOTHING); + return; + } + /* having failed to find a box, we try lines now. */ + if (!runmode && !altmod && !shiftmod) + { + t_linetraverser t; + t_outconnect *oc; + t_float fx = xpos, fy = ypos; + t_glist *glist2 = glist_getcanvas(x); + linetraverser_start(&t, glist2); + while ((oc = linetraverser_next(&t))) + { + t_float lx1 = t.tr_lx1, ly1 = t.tr_ly1, + lx2 = t.tr_lx2, ly2 = t.tr_ly2; + t_float area = (lx2 - lx1) * (fy - ly1) - + (ly2 - ly1) * (fx - lx1); + t_float dsquare = (lx2-lx1) * (lx2-lx1) + (ly2-ly1) * (ly2-ly1); + if (area * area >= 50 * dsquare) continue; + if ((lx2-lx1) * (fx-lx1) + (ly2-ly1) * (fy-ly1) < 0) continue; + if ((lx2-lx1) * (lx2-fx) + (ly2-ly1) * (ly2-fy) < 0) continue; + if (doit) + { + glist_selectline(glist2, oc, + canvas_getindex(glist2, &t.tr_ob->ob_g), t.tr_outno, + canvas_getindex(glist2, &t.tr_ob2->ob_g), t.tr_inno); + } + canvas_setcursor(x, CURSOR_EDITMODE_DISCONNECT); + return; + } + } + canvas_setcursor(x, CURSOR_EDITMODE_NOTHING); + if (doit) + { + if (!shiftmod) glist_noselect(x); + sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags x\n", + x, xpos, ypos, xpos, ypos); + x->gl_editor->e_xwas = xpos; + x->gl_editor->e_ywas = ypos; + x->gl_editor->e_onmotion = MA_REGION; + } +} + +void canvas_mouse(t_canvas *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg which, t_floatarg mod) +{ + canvas_doclick(x, xpos, ypos, which, mod, 1); +} + +int canvas_isconnected (t_canvas *x, t_text *ob1, int n1, + t_text *ob2, int n2) +{ + t_linetraverser t; + t_outconnect *oc; + linetraverser_start(&t, x); + while ((oc = linetraverser_next(&t))) + if (t.tr_ob == ob1 && t.tr_outno == n1 && + t.tr_ob2 == ob2 && t.tr_inno == n2) + return (1); + return (0); +} + +void canvas_doconnect(t_canvas *x, int xpos, int ypos, int which, int doit) +{ + int x11=0, y11=0, x12=0, y12=0; + t_gobj *y1; + int x21=0, y21=0, x22=0, y22=0; + t_gobj *y2; + int xwas = x->gl_editor->e_xwas, + ywas = x->gl_editor->e_ywas; + if (doit) sys_vgui(".x%lx.c delete x\n", x); + else sys_vgui(".x%lx.c coords x %d %d %d %d\n", + x, x->gl_editor->e_xwas, + x->gl_editor->e_ywas, xpos, ypos); + + if ((y1 = canvas_findhitbox(x, xwas, ywas, &x11, &y11, &x12, &y12)) + && (y2 = canvas_findhitbox(x, xpos, ypos, &x21, &y21, &x22, &y22))) + { + t_object *ob1 = pd_checkobject(&y1->g_pd); + t_object *ob2 = pd_checkobject(&y2->g_pd); + int noutlet1, ninlet2; + if (ob1 && ob2 && ob1 != ob2 && + (noutlet1 = obj_noutlets(ob1)) + && (ninlet2 = obj_ninlets(ob2))) + { + int width1 = x12 - x11, closest1, hotspot1; + int width2 = x22 - x21, closest2, hotspot2; + int lx1, lx2, ly1, ly2; + t_outconnect *oc; + + if (noutlet1 > 1) + { + closest1 = ((xwas-x11) * (noutlet1-1) + width1/2)/width1; + hotspot1 = x11 + + (width1 - IOWIDTH) * closest1 / (noutlet1-1); + } + else closest1 = 0, hotspot1 = x11; + + if (ninlet2 > 1) + { + closest2 = ((xpos-x21) * (ninlet2-1) + width2/2)/width2; + hotspot2 = x21 + + (width2 - IOWIDTH) * closest2 / (ninlet2-1); + } + else closest2 = 0, hotspot2 = x21; + + if (closest1 >= noutlet1) + closest1 = noutlet1 - 1; + if (closest2 >= ninlet2) + closest2 = ninlet2 - 1; + + if (canvas_isconnected (x, ob1, closest1, ob2, closest2)) + { + canvas_setcursor(x, CURSOR_EDITMODE_NOTHING); + return; + } + if (obj_issignaloutlet(ob1, closest1) && + !obj_issignalinlet(ob2, closest2)) + { + if (doit) + error("can't connect signal outlet to control inlet"); + canvas_setcursor(x, CURSOR_EDITMODE_NOTHING); + return; + } + if (doit) + { + int iow = IOWIDTH * x->gl_zoom; + int iom = IOMIDDLE * x->gl_zoom; + oc = obj_connect(ob1, closest1, ob2, closest2); + lx1 = x11 + (noutlet1 > 1 ? + ((x12-x11-iow) * closest1)/(noutlet1-1) : 0) + + iom; + ly1 = y12; + lx2 = x21 + (ninlet2 > 1 ? + ((x22-x21-iow) * closest2)/(ninlet2-1) : 0) + + iom; + ly2 = y21; + sys_vgui( + ".x%lx.c create line %d %d %d %d -width %d -tags [list l%lx cord]\n", + glist_getcanvas(x), + lx1, ly1, lx2, ly2, + (obj_issignaloutlet(ob1, closest1) ? 2 : 1) * + x->gl_zoom, + oc); + canvas_dirty(x, 1); + canvas_setundo(x, canvas_undo_connect, + canvas_undo_set_connect(x, + canvas_getindex(x, &ob1->ob_g), closest1, + canvas_getindex(x, &ob2->ob_g), closest2), + "connect"); + } + else canvas_setcursor(x, CURSOR_EDITMODE_CONNECT); + return; + } + } + canvas_setcursor(x, CURSOR_EDITMODE_NOTHING); +} + +void canvas_selectinrect(t_canvas *x, int lox, int loy, int hix, int hiy) +{ + t_gobj *y; + for (y = x->gl_list; y; y = y->g_next) + { + int x1, y1, x2, y2; + gobj_getrect(y, x, &x1, &y1, &x2, &y2); + if (hix >= x1 && lox <= x2 && hiy >= y1 && loy <= y2 + && !glist_isselected(x, y)) + glist_select(x, y); + } +} + +static void canvas_doregion(t_canvas *x, int xpos, int ypos, int doit) +{ + if (doit) + { + int lox, loy, hix, hiy; + if (x->gl_editor->e_xwas < xpos) + lox = x->gl_editor->e_xwas, hix = xpos; + else hix = x->gl_editor->e_xwas, lox = xpos; + if (x->gl_editor->e_ywas < ypos) + loy = x->gl_editor->e_ywas, hiy = ypos; + else hiy = x->gl_editor->e_ywas, loy = ypos; + canvas_selectinrect(x, lox, loy, hix, hiy); + sys_vgui(".x%lx.c delete x\n", x); + x->gl_editor->e_onmotion = MA_NONE; + } + else sys_vgui(".x%lx.c coords x %d %d %d %d\n", + x, x->gl_editor->e_xwas, + x->gl_editor->e_ywas, xpos, ypos); +} + +void canvas_mouseup(t_canvas *x, + t_floatarg fxpos, t_floatarg fypos, t_floatarg fwhich) +{ + int xpos = fxpos, ypos = fypos, which = fwhich; + /* post("mouseup %d %d %d", xpos, ypos, which); */ + if (!x->gl_editor) + { + bug("editor"); + return; + } + + EDITOR->canvas_upclicktime = sys_getrealtime(); + EDITOR->canvas_upx = xpos; + EDITOR->canvas_upy = ypos; + + if (x->gl_editor->e_onmotion == MA_CONNECT) + canvas_doconnect(x, xpos, ypos, which, 1); + else if (x->gl_editor->e_onmotion == MA_REGION) + canvas_doregion(x, xpos, ypos, 1); + else if (x->gl_editor->e_onmotion == MA_MOVE || + x->gl_editor->e_onmotion == MA_RESIZE) + { + /* after motion or resizing, if there's only one text item + selected, activate the text */ + if (x->gl_editor->e_selection && + !(x->gl_editor->e_selection->sel_next)) + { + t_gobj *g = x->gl_editor->e_selection->sel_what; + t_glist *gl2; + /* first though, check we aren't an abstraction with a + dirty sub-patch that would be discarded if we edit this. */ + if (pd_class(&g->g_pd) == canvas_class && + canvas_isabstraction((t_glist *)g) && + (gl2 = glist_finddirty((t_glist *)g))) + { + vmess(&gl2->gl_pd, gensym("menu-open"), ""); + x->gl_editor->e_onmotion = MA_NONE; + sys_vgui( +"pdtk_check .x%lx {Discard changes to '%s'?} {.x%lx dirty 0;\n} no\n", + canvas_getrootfor(gl2), + canvas_getrootfor(gl2)->gl_name->s_name, gl2); + return; + } + /* OK, activate it */ + gobj_activate(x->gl_editor->e_selection->sel_what, x, 1); + } + } + + x->gl_editor->e_onmotion = MA_NONE; +} + + /* displace the selection by (dx, dy) pixels */ +static void canvas_displaceselection(t_canvas *x, int dx, int dy) +{ + t_selection *y; + int resortin = 0, resortout = 0; + if (!EDITOR->canvas_undo_already_set_move) + { + canvas_setundo(x, canvas_undo_move, canvas_undo_set_move(x, 1), + "motion"); + EDITOR->canvas_undo_already_set_move = 1; + } + for (y = x->gl_editor->e_selection; y; y = y->sel_next) + { + t_class *cl = pd_class(&y->sel_what->g_pd); + gobj_displace(y->sel_what, x, dx, dy); + if (cl == vinlet_class) resortin = 1; + else if (cl == voutlet_class) resortout = 1; + } + if (resortin) canvas_resortinlets(x); + if (resortout) canvas_resortoutlets(x); + sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x); + if (x->gl_editor->e_selection) + canvas_dirty(x, 1); +} + + /* this routine is called whenever a key is pressed or released. "x" + may be zero if there's no current canvas. The first argument is true or + false for down/up; the second one is either a symbolic key name (e.g., + "Right" or an Ascii key number. The third is the shift key. */ +void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av) +{ + int keynum, fflag; + t_symbol *gotkeysym; + + int down, shift; + + if (ac < 3) + return; + + EDITOR->canvas_undo_already_set_move = 0; + down = (atom_getfloat(av) != 0); /* nonzero if it's a key down */ + shift = (atom_getfloat(av+2) != 0); /* nonzero if shift-ed */ + if (av[1].a_type == A_SYMBOL) + gotkeysym = av[1].a_w.w_symbol; + else if (av[1].a_type == A_FLOAT) + { + char buf[UTF8_MAXBYTES1]; + switch((int)(av[1].a_w.w_float)) + { + case 8: gotkeysym = gensym("BackSpace"); break; + case 9: gotkeysym = gensym("Tab"); break; + case 10: gotkeysym = gensym("Return"); break; + case 27: gotkeysym = gensym("Escape"); break; + case 32: gotkeysym = gensym("Space"); break; + case 127:gotkeysym = gensym("Delete"); break; + default: + /*-- moo: assume keynum is a Unicode codepoint; encode as UTF-8 --*/ + u8_wc_toutf8_nul(buf, (UCS4)(av[1].a_w.w_float)); + gotkeysym = gensym(buf); + } + } + else gotkeysym = gensym("?"); + fflag = (av[0].a_type == A_FLOAT ? av[0].a_w.w_float : 0); + keynum = (av[1].a_type == A_FLOAT ? av[1].a_w.w_float : 0); + if (keynum == '\\' || keynum == '{' || keynum == '}') + { + post("keycode %d: dropped", (int)keynum); + return; + } +#if 0 + post("keynum %d, down %d", (int)keynum, down); +#endif + if (keynum == '\r') keynum = '\n'; + if (av[1].a_type == A_SYMBOL && + !strcmp(av[1].a_w.w_symbol->s_name, "Return")) + keynum = '\n'; + /* alias Apple key numbers to symbols. This is done unconditionally, + not just if we're on an Apple, just in case the GUI is remote. */ + if (keynum == 30 || keynum == 63232) + keynum = 0, gotkeysym = gensym("Up"); + else if (keynum == 31 || keynum == 63233) + keynum = 0, gotkeysym = gensym("Down"); + else if (keynum == 28 || keynum == 63234) + keynum = 0, gotkeysym = gensym("Left"); + else if (keynum == 29 || keynum == 63235) + keynum = 0, gotkeysym = gensym("Right"); + else if (keynum == 63273) + keynum = 0, gotkeysym = gensym("Home"); + else if (keynum == 63275) + keynum = 0, gotkeysym = gensym("End"); + else if (keynum == 63276) + keynum = 0, gotkeysym = gensym("Prior"); + else if (keynum == 63277) + keynum = 0, gotkeysym = gensym("Next"); + if (gensym("#key")->s_thing && down) + pd_float(gensym("#key")->s_thing, (t_float)keynum); + if (gensym("#keyup")->s_thing && !down) + pd_float(gensym("#keyup")->s_thing, (t_float)keynum); + if (gensym("#keyname")->s_thing) + { + t_atom at[2]; + at[0] = av[0]; + SETFLOAT(at, down); + SETSYMBOL(at+1, gotkeysym); + pd_list(gensym("#keyname")->s_thing, 0, 2, at); + } + if (!x || !x->gl_editor) /* if that 'invis'ed the window, stop. */ + return; + if (x && down) + { + t_object *ob; + /* cancel any dragging action */ + if (x->gl_editor->e_onmotion == MA_MOVE) + x->gl_editor->e_onmotion = MA_NONE; + /* if an object has "grabbed" keys just send them on */ + if (x->gl_editor->e_grab + && x->gl_editor->e_keyfn && keynum) + (* x->gl_editor->e_keyfn) + (x->gl_editor->e_grab, (t_float)keynum); + /* if a text editor is open send the key on, as long as + it is either "real" (has a key number) or else is an arrow key. */ + else if (x->gl_editor->e_textedfor && (keynum + || !strcmp(gotkeysym->s_name, "Up") + || !strcmp(gotkeysym->s_name, "Down") + || !strcmp(gotkeysym->s_name, "Left") + || !strcmp(gotkeysym->s_name, "Right"))) + { + /* send the key to the box's editor */ + if (!x->gl_editor->e_textdirty) + { + canvas_setundo(x, canvas_undo_cut, + canvas_undo_set_cut(x, UCUT_TEXT), "typing"); + } + rtext_key(x->gl_editor->e_textedfor, + (int)keynum, gotkeysym); + if (x->gl_editor->e_textdirty) + canvas_dirty(x, 1); + } + /* check for backspace or clear */ + else if (keynum == 8 || keynum == 127) + { + if (x->gl_editor->e_selectedline) + canvas_clearline(x); + else if (x->gl_editor->e_selection) + { + canvas_setundo(x, canvas_undo_cut, + canvas_undo_set_cut(x, UCUT_CLEAR), "clear"); + canvas_doclear(x); + } + } + /* check for arrow keys */ + else if (!strcmp(gotkeysym->s_name, "Up")) + canvas_displaceselection(x, 0, shift ? -10 : -1); + else if (!strcmp(gotkeysym->s_name, "Down")) + canvas_displaceselection(x, 0, shift ? 10 : 1); + else if (!strcmp(gotkeysym->s_name, "Left")) + canvas_displaceselection(x, shift ? -10 : -1, 0); + else if (!strcmp(gotkeysym->s_name, "Right")) + canvas_displaceselection(x, shift ? 10 : 1, 0); + } + /* if control key goes up or down, and if we're in edit mode, change + cursor to indicate how the click action changes */ + if (x && keynum == 0 && x->gl_edit && + !strncmp(gotkeysym->s_name, "Control", 7)) + canvas_setcursor(x, down ? + CURSOR_RUNMODE_NOTHING :CURSOR_EDITMODE_NOTHING); +} + +static void delay_move(t_canvas *x) +{ + canvas_displaceselection(x, + x->gl_editor->e_xnew - x->gl_editor->e_xwas, + x->gl_editor->e_ynew - x->gl_editor->e_ywas); + x->gl_editor->e_xwas = x->gl_editor->e_xnew; + x->gl_editor->e_ywas = x->gl_editor->e_ynew; +} + +void canvas_motion(t_canvas *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg fmod) +{ + /* post("motion %d %d", xpos, ypos); */ + int mod = fmod; + if (!x->gl_editor) + { + bug("editor"); + return; + } + glist_setlastxy(x, xpos, ypos); + if (x->gl_editor->e_onmotion == MA_MOVE) + { + if (!x->gl_editor->e_clock) + x->gl_editor->e_clock = clock_new(x, (t_method)delay_move); + clock_unset(x->gl_editor->e_clock); + clock_delay(x->gl_editor->e_clock, 5); + x->gl_editor->e_xnew = xpos; + x->gl_editor->e_ynew = ypos; + } + else if (x->gl_editor->e_onmotion == MA_REGION) + canvas_doregion(x, xpos, ypos, 0); + else if (x->gl_editor->e_onmotion == MA_CONNECT) + canvas_doconnect(x, xpos, ypos, 0, 0); + else if (x->gl_editor->e_onmotion == MA_PASSOUT) + { + if (!x->gl_editor->e_motionfn) + bug("e_motionfn"); + (*x->gl_editor->e_motionfn)(&x->gl_editor->e_grab->g_pd, + xpos - x->gl_editor->e_xwas, + ypos - x->gl_editor->e_ywas); + x->gl_editor->e_xwas = xpos; + x->gl_editor->e_ywas = ypos; + } + else if (x->gl_editor->e_onmotion == MA_DRAGTEXT) + { + t_rtext *rt = x->gl_editor->e_textedfor; + if (rt) + rtext_mouse(rt, xpos - x->gl_editor->e_xwas, + ypos - x->gl_editor->e_ywas, RTEXT_DRAG); + } + else if (x->gl_editor->e_onmotion == MA_RESIZE) + { + int x11=0, y11=0, x12=0, y12=0; + t_gobj *y1; + if ((y1 = canvas_findhitbox(x, + x->gl_editor->e_xwas, x->gl_editor->e_ywas, + &x11, &y11, &x12, &y12))) + { + int wantwidth = xpos - x11; + t_gotfn sizefn; + t_object *ob = pd_checkobject(&y1->g_pd); + if (ob && ((ob->te_pd->c_wb == &text_widgetbehavior) || + (pd_checkglist(&ob->te_pd) && + !((t_canvas *)ob)->gl_isgraph))) + { + wantwidth = wantwidth / glist_fontwidth(x); + if (wantwidth < 1) + wantwidth = 1; + ob->te_width = wantwidth; + gobj_vis(y1, x, 0); + canvas_fixlinesfor(x, ob); + gobj_vis(y1, x, 1); + } + else if (ob && ob->ob_pd == canvas_class) + { + gobj_vis(y1, x, 0); + ((t_canvas *)ob)->gl_pixwidth += xpos - x->gl_editor->e_xnew; + ((t_canvas *)ob)->gl_pixheight += ypos - x->gl_editor->e_ynew; + x->gl_editor->e_xnew = xpos; + x->gl_editor->e_ynew = ypos; + canvas_fixlinesfor(x, ob); + gobj_vis(y1, x, 1); + } + else post("not resizable"); + } + } + else canvas_doclick(x, xpos, ypos, 0, mod, 0); + + x->gl_editor->e_lastmoved = 1; +} + +void canvas_startmotion(t_canvas *x) +{ + int xval, yval; + if (!x->gl_editor) return; + glist_getnextxy(x, &xval, &yval); + if (xval == 0 && yval == 0) return; + x->gl_editor->e_onmotion = MA_MOVE; + x->gl_editor->e_xwas = xval; + x->gl_editor->e_ywas = yval; +} + +/* ----------------------------- window stuff ----------------------- */ +extern int sys_perf; + +void canvas_print(t_canvas *x, t_symbol *s) +{ + if (*s->s_name) sys_vgui(".x%lx.c postscript -file %s\n", x, s->s_name); + else sys_vgui(".x%lx.c postscript -file x.ps\n", x); +} + + /* find a dirty sub-glist, if any, of this one (including itself) */ +static t_glist *glist_finddirty(t_glist *x) +{ + t_gobj *g; + t_glist *g2; + if (x->gl_env && x->gl_dirty) + return (x); + for (g = x->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd) == canvas_class && + (g2 = glist_finddirty((t_glist *)g))) + return (g2); + return (0); +} + + /* quit, after calling glist_finddirty() on all toplevels and verifying + the user really wants to discard changes */ +void glob_verifyquit(void *dummy, t_floatarg f) +{ + t_glist *g, *g2; + /* find all root canvases */ + for (g = pd_getcanvaslist(); g; g = g->gl_next) + if ((g2 = glist_finddirty(g))) + { + canvas_vis(g2, 1); + sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 3;\n}\n", + canvas_getrootfor(g2), g2); + return; + } + if (f == 0 && sys_perf) + sys_vgui("pdtk_check .pdwindow {really quit?} {pd quit} yes\n"); + else glob_quit(0); +} + + /* close a window (or possibly quit Pd), checking for dirty flags. + The "force" parameter is interpreted as follows: + 0 - request from GUI to close, verifying whether clean or dirty + 1 - request from GUI to close, no verification + 2 - verified - mark this one clean, then continue as in 1 + 3 - verified - mark this one clean, then verify-and-quit + */ +void canvas_menuclose(t_canvas *x, t_floatarg fforce) +{ + int force = fforce; + t_glist *g; + if ((x->gl_owner || x->gl_isclone) && (force == 0 || force == 1)) + canvas_vis(x, 0); /* if subpatch, just invis it */ + else if (force == 0) + { + g = glist_finddirty(x); + if (g) + { + vmess(&g->gl_pd, gensym("menu-open"), ""); + sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;\n}\n", + canvas_getrootfor(g), g); + return; + } + else if (sys_perf) + { + sys_vgui( + "pdtk_check .x%lx {Close this window?} {.x%lx menuclose 1;\n} yes\n", + canvas_getrootfor(x), x); + } + else pd_free(&x->gl_pd); + } + else if (force == 1) + pd_free(&x->gl_pd); + else if (force == 2) + { + canvas_dirty(x, 0); + while (x->gl_owner) + x = x->gl_owner; + g = glist_finddirty(x); + if (g) + { + vmess(&g->gl_pd, gensym("menu-open"), ""); + sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;\n}\n", + canvas_getrootfor(x), g); + return; + } + else pd_free(&x->gl_pd); + } + else if (force == 3) + { + canvas_dirty(x, 0); + glob_verifyquit(0, 1); + } +} + + /* put up a dialog which may call canvas_font back to do the work */ +static void canvas_menufont(t_canvas *x) +{ + char buf[80]; + t_canvas *x2 = canvas_getrootfor(x); + gfxstub_deleteforkey(x2); + sprintf(buf, "pdtk_canvas_dofont %%s %d\n", x2->gl_font); + gfxstub_new(&x2->gl_pd, &x2->gl_pd, buf); +} + +typedef void (*t_zoomfn)(void *x, t_floatarg arg1); + +#define REZOOM(x, y) ((x) = ((y) == 2 ? (x)*2 : (x)/2)) +static void canvas_zoom(t_canvas *x, t_floatarg zoom) +{ + if (zoom != x->gl_zoom && (zoom == 1 || zoom == 2)) + { + t_gobj *g; + t_object *obj; + for (g = x->gl_list; g; g = g->g_next) + if ((obj = pd_checkobject(&g->g_pd))) + { + t_gotfn zoommethod; + REZOOM(obj->te_xpix, zoom); + REZOOM(obj->te_ypix, zoom); + /* pass zoom message on to all objects, except canvases + that aren't GOP */ + if ((zoommethod = zgetfn(&obj->te_pd, gensym("zoom"))) && + (!(pd_class(&obj->te_pd) == canvas_class) || + (((t_glist *)obj)->gl_isgraph))) + (*(t_zoomfn)zoommethod)(&obj->te_pd, zoom); + } + x->gl_zoom = zoom; + REZOOM(x->gl_xmargin, zoom); + REZOOM(x->gl_ymargin, zoom); + REZOOM(x->gl_pixwidth, zoom); + REZOOM(x->gl_pixheight, zoom); + if (x->gl_havewindow) + canvas_redraw(x); + } +} + + /* function to support searching */ +static int atoms_match(int inargc, t_atom *inargv, int searchargc, + t_atom *searchargv, int wholeword) +{ + int indexin, nmatched; + for (indexin = 0; indexin <= inargc - searchargc; indexin++) + { + for (nmatched = 0; nmatched < searchargc; nmatched++) + { + t_atom *a1 = &inargv[indexin + nmatched], + *a2 = &searchargv[nmatched]; + if (a1->a_type == A_SEMI || a1->a_type == A_COMMA) + { + if (a2->a_type != a1->a_type) + goto nomatch; + } + else if (a1->a_type == A_FLOAT || a1->a_type == A_DOLLAR) + { + if (a2->a_type != a1->a_type || + a1->a_w.w_float != a2->a_w.w_float) + goto nomatch; + } + else if (a1->a_type == A_SYMBOL || a1->a_type == A_DOLLSYM) + { + if ((a2->a_type != A_SYMBOL && a2->a_type != A_DOLLSYM) + || (wholeword && a1->a_w.w_symbol != a2->a_w.w_symbol) + || (!wholeword && !strstr(a1->a_w.w_symbol->s_name, + a2->a_w.w_symbol->s_name))) + goto nomatch; + } + } + return (1); + nomatch: ; + } + return (0); +} + + /* find an atom or string of atoms */ +static int canvas_dofind(t_canvas *x, int *myindexp) +{ + t_gobj *y; + int findargc = binbuf_getnatom(EDITOR->canvas_findbuf), didit = 0; + t_atom *findargv = binbuf_getvec(EDITOR->canvas_findbuf); + for (y = x->gl_list; y; y = y->g_next) + { + t_object *ob = 0; + if ((ob = pd_checkobject(&y->g_pd))) + { + if (atoms_match(binbuf_getnatom(ob->ob_binbuf), + binbuf_getvec(ob->ob_binbuf), findargc, findargv, + EDITOR->canvas_find_wholeword)) + { + if (*myindexp == EDITOR->canvas_find_index) + { + glist_noselect(x); + vmess(&x->gl_pd, gensym("menu-open"), ""); + canvas_editmode(x, 1.); + glist_select(x, y); + didit = 1; + } + (*myindexp)++; + } + } + } + for (y = x->gl_list; y; y = y->g_next) + if (pd_class(&y->g_pd) == canvas_class) + didit |= canvas_dofind((t_canvas *)y, myindexp); + return (didit); +} + +static void canvas_find(t_canvas *x, t_symbol *s, t_floatarg wholeword) +{ + int myindex = 0, found; + t_symbol *decodedsym = sys_decodedialog(s); + if (!EDITOR->canvas_findbuf) + EDITOR->canvas_findbuf = binbuf_new(); + binbuf_text(EDITOR->canvas_findbuf, decodedsym->s_name, + strlen(decodedsym->s_name)); + EDITOR->canvas_find_index = 0; + EDITOR->canvas_find_wholeword = wholeword; + canvas_whichfind = x; + found = canvas_dofind(x, &myindex); + if (found) + EDITOR->canvas_find_index = 1; + sys_vgui("pdtk_showfindresult .x%lx %d %d %d\n", x, found, + EDITOR->canvas_find_index, myindex); +} + +static void canvas_find_again(t_canvas *x) +{ + int myindex = 0, found; + if (!EDITOR->canvas_findbuf || !canvas_whichfind) + return; + found = canvas_dofind(canvas_whichfind, &myindex); + sys_vgui("pdtk_showfindresult .x%lx %d %d %d\n", x, found, + ++EDITOR->canvas_find_index, myindex); + if (!found) + EDITOR->canvas_find_index = 0; +} + +static void canvas_find_parent(t_canvas *x) +{ + if (x->gl_owner) + canvas_vis(glist_getcanvas(x->gl_owner), 1); +} + +static int glist_dofinderror(t_glist *gl, void *error_object) +{ + t_gobj *g; + for (g = gl->gl_list; g; g = g->g_next) + { + if ((void *)g == error_object) + { + /* got it... now show it. */ + glist_noselect(gl); + canvas_vis(glist_getcanvas(gl), 1); + canvas_editmode(glist_getcanvas(gl), 1.); + glist_select(gl, g); + return (1); + } + else if (g->g_pd == canvas_class) + { + if (glist_dofinderror((t_canvas *)g, error_object)) + return (1); + } + } + return (0); +} + +void canvas_finderror(void *error_object) +{ + t_canvas *x; + /* find all root canvases */ + for (x = pd_getcanvaslist(); x; x = x->gl_next) + { + if (glist_dofinderror(x, error_object)) + return; + } + error("... sorry, I couldn't find the source of that error."); +} + +void canvas_stowconnections(t_canvas *x) +{ + t_gobj *selhead = 0, *seltail = 0, *nonhead = 0, *nontail = 0, *y, *y2; + t_linetraverser t; + t_outconnect *oc; + if (!x->gl_editor) return; + /* split list to "selected" and "unselected" parts */ + for (y = x->gl_list; y; y = y2) + { + y2 = y->g_next; + if (glist_isselected(x, y)) + { + if (seltail) + { + seltail->g_next = y; + seltail = y; + y->g_next = 0; + } + else + { + selhead = seltail = y; + seltail->g_next = 0; + } + } + else + { + if (nontail) + { + nontail->g_next = y; + nontail = y; + y->g_next = 0; + } + else + { + nonhead = nontail = y; + nontail->g_next = 0; + } + } + } + /* move the selected part to the end */ + if (!nonhead) x->gl_list = selhead; + else x->gl_list = nonhead, nontail->g_next = selhead; + + /* add connections to binbuf */ + binbuf_clear(x->gl_editor->e_connectbuf); + linetraverser_start(&t, x); + while ((oc = linetraverser_next(&t))) + { + int s1 = glist_isselected(x, &t.tr_ob->ob_g); + int s2 = glist_isselected(x, &t.tr_ob2->ob_g); + if (s1 != s2) + binbuf_addv(x->gl_editor->e_connectbuf, "ssiiii;", + gensym("#X"), gensym("connect"), + glist_getindex(x, &t.tr_ob->ob_g), t.tr_outno, + glist_getindex(x, &t.tr_ob2->ob_g), t.tr_inno); + } +} + +void canvas_restoreconnections(t_canvas *x) +{ + t_pd *boundx = s__X.s_thing; + s__X.s_thing = &x->gl_pd; + binbuf_eval(x->gl_editor->e_connectbuf, 0, 0, 0); + s__X.s_thing = boundx; +} + +static t_binbuf *canvas_docopy(t_canvas *x) +{ + t_gobj *y; + t_linetraverser t; + t_outconnect *oc; + t_binbuf *b = binbuf_new(); + for (y = x->gl_list; y; y = y->g_next) + { + if (glist_isselected(x, y)) + gobj_save(y, b); + } + linetraverser_start(&t, x); + while ((oc = linetraverser_next(&t))) + { + if (glist_isselected(x, &t.tr_ob->ob_g) + && glist_isselected(x, &t.tr_ob2->ob_g)) + { + binbuf_addv(b, "ssiiii;", gensym("#X"), gensym("connect"), + glist_selectionindex(x, &t.tr_ob->ob_g, 1), t.tr_outno, + glist_selectionindex(x, &t.tr_ob2->ob_g, 1), t.tr_inno); + } + } + return (b); +} + +static void canvas_copy(t_canvas *x) +{ + if (!x->gl_editor || !x->gl_editor->e_selection) + return; + binbuf_free(EDITOR->copy_binbuf); + EDITOR->copy_binbuf = canvas_docopy(x); + if (x->gl_editor->e_textedfor) + { + char *buf; + int bufsize; + rtext_getseltext(x->gl_editor->e_textedfor, &buf, &bufsize); + sys_gui("clipboard clear\n"); + sys_vgui("clipboard append {%.*s}\n", bufsize, buf); + } +} + +static void canvas_clearline(t_canvas *x) +{ + if (x->gl_editor->e_selectedline) + { + canvas_disconnect(x, x->gl_editor->e_selectline_index1, + x->gl_editor->e_selectline_outno, + x->gl_editor->e_selectline_index2, + x->gl_editor->e_selectline_inno); + canvas_dirty(x, 1); + canvas_setundo(x, canvas_undo_disconnect, + canvas_undo_set_disconnect(x, + x->gl_editor->e_selectline_index1, + x->gl_editor->e_selectline_outno, + x->gl_editor->e_selectline_index2, + x->gl_editor->e_selectline_inno), + "disconnect"); + } +} + +static void canvas_doclear(t_canvas *x) +{ + t_gobj *y, *y2; + int dspstate; + + dspstate = canvas_suspend_dsp(); + if (x->gl_editor->e_selectedline) + { + canvas_disconnect(x, x->gl_editor->e_selectline_index1, + x->gl_editor->e_selectline_outno, + x->gl_editor->e_selectline_index2, + x->gl_editor->e_selectline_inno); + canvas_setundo(x, canvas_undo_disconnect, + canvas_undo_set_disconnect(x, + x->gl_editor->e_selectline_index1, + x->gl_editor->e_selectline_outno, + x->gl_editor->e_selectline_index2, + x->gl_editor->e_selectline_inno), + "disconnect"); + } + /* if text is selected, deselecting it might remake the + object. So we deselect it and hunt for a "new" object on + the glist to reselect. */ + if (x->gl_editor->e_textedfor) + { + t_gobj *selwas = x->gl_editor->e_selection->sel_what; + pd_this->pd_newest = 0; + glist_noselect(x); + if (pd_this->pd_newest) + { + for (y = x->gl_list; y; y = y->g_next) + if (&y->g_pd == pd_this->pd_newest) glist_select(x, y); + } + } + while (1) /* this is pretty weird... should rewrite it */ + { + for (y = x->gl_list; y; y = y2) + { + y2 = y->g_next; + if (glist_isselected(x, y)) + { + glist_delete(x, y); + goto next; + } + } + goto restore; + next: ; + } +restore: + canvas_resume_dsp(dspstate); + canvas_dirty(x, 1); +} + +static void canvas_cut(t_canvas *x) +{ + if (!x->gl_editor) /* ignore if invisible */ + return; + if (x->gl_editor && x->gl_editor->e_selectedline) /* delete line */ + canvas_clearline(x); + else if (x->gl_editor->e_textedfor) /* delete selected text in a box */ + { + char *buf; + int bufsize; + rtext_getseltext(x->gl_editor->e_textedfor, &buf, &bufsize); + if (!bufsize && x->gl_editor->e_selection && + !x->gl_editor->e_selection->sel_next) + { + /* if the text is already empty, delete the box. We + first clear 'textedfor' so that canvas_doclear later will + think the whole box was selected, not the text */ + x->gl_editor->e_textedfor = 0; + goto deleteobj; + } + canvas_copy(x); + rtext_key(x->gl_editor->e_textedfor, 127, &s_); + canvas_dirty(x, 1); + } + else if (x->gl_editor && x->gl_editor->e_selection) + { + deleteobj: /* delete one or more objects */ + canvas_setundo(x, canvas_undo_cut, + canvas_undo_set_cut(x, UCUT_CUT), "cut"); + canvas_copy(x); + canvas_doclear(x); + sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x); + } +} + +static void glist_donewloadbangs(t_glist *x) +{ + if (x->gl_editor) + { + t_selection *sel; + for (sel = x->gl_editor->e_selection; sel; sel = sel->sel_next) + if (pd_class(&sel->sel_what->g_pd) == canvas_class) + canvas_loadbang((t_canvas *)(&sel->sel_what->g_pd)); + else if (zgetfn(&sel->sel_what->g_pd, gensym("loadbang"))) + vmess(&sel->sel_what->g_pd, gensym("loadbang"), "f", LB_LOAD); + } +} + +static void canvas_dopaste(t_canvas *x, t_binbuf *b) +{ + t_gobj *newgobj, *last, *g2; + int dspstate = canvas_suspend_dsp(), nbox, count; + t_symbol *asym = gensym("#A"); + /* save and clear bindings to symbols #a, $N, $X; restore when done */ + t_pd *boundx = s__X.s_thing, *bounda = asym->s_thing, + *boundn = s__N.s_thing; + asym->s_thing = 0; + s__X.s_thing = &x->gl_pd; + s__N.s_thing = &pd_canvasmaker; + + canvas_editmode(x, 1.); + glist_noselect(x); + for (g2 = x->gl_list, nbox = 0; g2; g2 = g2->g_next) nbox++; + + EDITOR->paste_onset = nbox; + EDITOR->paste_canvas = x; + + binbuf_eval(b, 0, 0, 0); + for (g2 = x->gl_list, count = 0; g2; g2 = g2->g_next, count++) + if (count >= nbox) + glist_select(x, g2); + EDITOR->paste_canvas = 0; + canvas_resume_dsp(dspstate); + canvas_dirty(x, 1); + if (x->gl_mapped) + sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x); + if (!sys_noloadbang) + glist_donewloadbangs(x); + asym->s_thing = bounda; + s__X.s_thing = boundx; + s__N.s_thing = boundn; +} + +static void canvas_paste(t_canvas *x) +{ + if (!x->gl_editor) + return; + if (x->gl_editor->e_textedfor) + { + /* simulate keystrokes as if the copy buffer were typed in. */ + sys_vgui("pdtk_pastetext .x%lx\n", x); + } + else + { + canvas_setundo(x, canvas_undo_paste, canvas_undo_set_paste(x), + "paste"); + canvas_dopaste(x, EDITOR->copy_binbuf); + } +} + +static void canvas_duplicate(t_canvas *x) +{ + if (!x->gl_editor) + return; + if (x->gl_editor->e_onmotion == MA_NONE && x->gl_editor->e_selection) + { + t_selection *y; + canvas_copy(x); + canvas_setundo(x, canvas_undo_paste, canvas_undo_set_paste(x), + "duplicate"); + canvas_dopaste(x, EDITOR->copy_binbuf); + for (y = x->gl_editor->e_selection; y; y = y->sel_next) + gobj_displace(y->sel_what, x, + 10, 10); + canvas_dirty(x, 1); + } +} + +static void canvas_selectall(t_canvas *x) +{ + t_gobj *y; + if (!x->gl_editor) + return; + if (!x->gl_edit) + canvas_editmode(x, 1); + /* if everyone is already selected deselect everyone */ + if (!glist_selectionindex(x, 0, 0)) + glist_noselect(x); + else for (y = x->gl_list; y; y = y->g_next) + { + if (!glist_isselected(x, y)) + glist_select(x, y); + } +} + +static void canvas_reselect(t_canvas *x) +{ + t_gobj *g, *gwas; + t_selection *sel; + t_object *ob; + /* if someone is text editing, and if only one object is + selected, deselect everyone and reselect. */ + if (x->gl_editor->e_textedfor) + { + /* only do this if exactly one item is selected. */ + if ((gwas = x->gl_editor->e_selection->sel_what) && + !x->gl_editor->e_selection->sel_next) + { + int nobjwas = glist_getindex(x, 0), + indx = canvas_getindex(x, x->gl_editor->e_selection->sel_what); + glist_noselect(x); + for (g = x->gl_list; g; g = g->g_next) + if (g == gwas) + { + glist_select(x, g); + return; + } + /* "gwas" must have disappeared; just search to the last + object and select it */ + for (g = x->gl_list; g; g = g->g_next) + if (!g->g_next) + glist_select(x, g); + } + } + else if (x->gl_editor->e_selection && + !x->gl_editor->e_selection->sel_next) + /* otherwise activate first item in selection */ + gobj_activate(x->gl_editor->e_selection->sel_what, x, 1); +} + +extern t_class *text_class; + +void canvas_connect(t_canvas *x, t_floatarg fwhoout, t_floatarg foutno, + t_floatarg fwhoin, t_floatarg finno) +{ + int whoout = fwhoout, outno = foutno, whoin = fwhoin, inno = finno; + t_gobj *src = 0, *sink = 0; + t_object *objsrc, *objsink; + t_outconnect *oc; + int nin = whoin, nout = whoout; + if (EDITOR->paste_canvas == x) whoout += EDITOR->paste_onset, + whoin += EDITOR->paste_onset; + for (src = x->gl_list; whoout; src = src->g_next, whoout--) + if (!src->g_next) goto bad; /* bug fix thanks to Hannes */ + for (sink = x->gl_list; whoin; sink = sink->g_next, whoin--) + if (!sink->g_next) goto bad; + + /* check they're both patchable objects */ + if (!(objsrc = pd_checkobject(&src->g_pd)) || + !(objsink = pd_checkobject(&sink->g_pd))) + goto bad; + + /* if object creation failed, make dummy inlets or outlets + as needed */ + if (pd_class(&src->g_pd) == text_class && objsrc->te_type == T_OBJECT) + while (outno >= obj_noutlets(objsrc)) + outlet_new(objsrc, 0); + if (pd_class(&sink->g_pd) == text_class && objsink->te_type == T_OBJECT) + while (inno >= obj_ninlets(objsink)) + inlet_new(objsink, &objsink->ob_pd, 0, 0); + + if (!(oc = obj_connect(objsrc, outno, objsink, inno))) goto bad; + if (glist_isvisible(x)) + { + sys_vgui( + ".x%lx.c create line %d %d %d %d -width %d -tags [list l%lx cord]\n", + glist_getcanvas(x), 0, 0, 0, 0, + (obj_issignaloutlet(objsrc, outno) ? 2 : 1) * x->gl_zoom, oc); + canvas_fixlinesfor(x, objsrc); + } + return; + +bad: + post("%s %d %d %d %d (%s->%s) connection failed", + x->gl_name->s_name, nout, outno, nin, inno, + (src? class_getname(pd_class(&src->g_pd)) : "???"), + (sink? class_getname(pd_class(&sink->g_pd)) : "???")); +} + +#define XTOLERANCE 18 +#define YTOLERANCE 17 +#define NHIST 35 + + /* LATER might have to speed this up */ +static void canvas_tidy(t_canvas *x) +{ + t_gobj *y, *y2, *y3; + int ax1, ay1, ax2, ay2, bx1, by1, bx2, by2; + int histogram[NHIST], *ip, i, besthist, bestdist; + /* if nobody is selected, this means do it to all boxes; + othewise just the selection */ + int all = (x->gl_editor ? (x->gl_editor->e_selection == 0) : 1); + + canvas_setundo(x, canvas_undo_move, canvas_undo_set_move(x, !all), + "motion"); + + /* tidy horizontally */ + for (y = x->gl_list; y; y = y->g_next) + if (all || glist_isselected(x, y)) + { + gobj_getrect(y, x, &ax1, &ay1, &ax2, &ay2); + + for (y2 = x->gl_list; y2; y2 = y2->g_next) + if (all || glist_isselected(x, y2)) + { + gobj_getrect(y2, x, &bx1, &by1, &bx2, &by2); + if (by1 <= ay1 + YTOLERANCE && by1 >= ay1 - YTOLERANCE && + bx1 < ax1) + goto nothorizhead; + } + + for (y2 = x->gl_list; y2; y2 = y2->g_next) + if (all || glist_isselected(x, y2)) + { + gobj_getrect(y2, x, &bx1, &by1, &bx2, &by2); + if (by1 <= ay1 + YTOLERANCE && by1 >= ay1 - YTOLERANCE + && by1 != ay1) + gobj_displace(y2, x, 0, ay1-by1); + } + nothorizhead: ; + } + /* tidy vertically. First guess the user's favorite vertical spacing */ + for (i = NHIST, ip = histogram; i--; ip++) *ip = 0; + for (y = x->gl_list; y; y = y->g_next) + if (all || glist_isselected(x, y)) + { + gobj_getrect(y, x, &ax1, &ay1, &ax2, &ay2); + for (y2 = x->gl_list; y2; y2 = y2->g_next) + if (all || glist_isselected(x, y2)) + { + gobj_getrect(y2, x, &bx1, &by1, &bx2, &by2); + if (bx1 <= ax1 + XTOLERANCE && bx1 >= ax1 - XTOLERANCE) + { + int distance = by1-ay2; + if (distance >= 0 && distance < NHIST) + histogram[distance]++; + } + } + } + for (i = 2, besthist = 0, bestdist = 4, ip = histogram + 2; + i < (NHIST-2); i++, ip++) + { + int hit = ip[-2] + 2 * ip[-1] + 3 * ip[0] + 2* ip[1] + ip[2]; + if (hit > besthist) + { + besthist = hit; + bestdist = i; + } + } + post("best vertical distance %d", bestdist); + for (y = x->gl_list; y; y = y->g_next) + if (all || glist_isselected(x, y)) + { + int keep = 1; + gobj_getrect(y, x, &ax1, &ay1, &ax2, &ay2); + for (y2 = x->gl_list; y2; y2 = y2->g_next) + if (all || glist_isselected(x, y2)) + { + gobj_getrect(y2, x, &bx1, &by1, &bx2, &by2); + if (bx1 <= ax1 + XTOLERANCE && bx1 >= ax1 - XTOLERANCE && + ay1 >= by2 - 10 && ay1 < by2 + NHIST) + goto nothead; + } + while (keep) + { + keep = 0; + for (y2 = x->gl_list; y2; y2 = y2->g_next) + if (all || glist_isselected(x, y2)) + { + gobj_getrect(y2, x, &bx1, &by1, &bx2, &by2); + if (bx1 <= ax1 + XTOLERANCE && bx1 >= ax1 - XTOLERANCE && + by1 > ay1 && by1 < ay2 + NHIST) + { + int vmove = ay2 + bestdist - by1; + gobj_displace(y2, x, ax1-bx1, vmove); + ay1 = by1 + vmove; + ay2 = by2 + vmove; + keep = 1; + break; + } + } + } + nothead: ; + } + canvas_dirty(x, 1); +} + +static void canvas_texteditor(t_canvas *x) +{ + t_rtext *foo; + char *buf; + int bufsize; + if ((foo = x->gl_editor->e_textedfor)) + rtext_gettext(foo, &buf, &bufsize); + else buf = "", bufsize = 0; + sys_vgui("pdtk_pd_texteditor {%.*s}\n", bufsize, buf); + +} + +void glob_key(void *dummy, t_symbol *s, int ac, t_atom *av) +{ + /* canvas_key checks for zero */ + canvas_key(0, s, ac, av); +} + +void canvas_editmode(t_canvas *x, t_floatarg state) +{ + if (x->gl_edit == (unsigned int) state) + return; + x->gl_edit = (unsigned int) state; + if (x->gl_edit && glist_isvisible(x) && glist_istoplevel(x)) + { + t_gobj *g; + t_object *ob; + canvas_setcursor(x, CURSOR_EDITMODE_NOTHING); + for (g = x->gl_list; g; g = g->g_next) + if ((ob = pd_checkobject(&g->g_pd)) && ob->te_type == T_TEXT) + { + t_rtext *y = glist_findrtext(x, ob); + text_drawborder(ob, x, + rtext_gettag(y), rtext_width(y), rtext_height(y), 1); + } + } + else + { + glist_noselect(x); + if (glist_isvisible(x) && glist_istoplevel(x)) + { + canvas_setcursor(x, CURSOR_RUNMODE_NOTHING); + sys_vgui(".x%lx.c delete commentbar\n", glist_getcanvas(x)); + } + } + if (glist_isvisible(x)) + sys_vgui("pdtk_canvas_editmode .x%lx %d\n", + glist_getcanvas(x), x->gl_edit); + canvas_reflecttitle(x); +} + + /* called by canvas_font below */ +static void canvas_dofont(t_canvas *x, t_floatarg font, t_floatarg xresize, + t_floatarg yresize) +{ + t_gobj *y; + x->gl_font = font; + if (xresize != 1 || yresize != 1) + { + canvas_setundo(x, canvas_undo_move, canvas_undo_set_move(x, 0), + "motion"); + for (y = x->gl_list; y; y = y->g_next) + { + int x1, x2, y1, y2, nx1, ny1; + gobj_getrect(y, x, &x1, &y1, &x2, &y2); + nx1 = x1 * xresize + 0.5; + ny1 = y1 * yresize + 0.5; + gobj_displace(y, x, nx1-x1, ny1-y1); + } + } + if (glist_isvisible(x)) + glist_redraw(x); + for (y = x->gl_list; y; y = y->g_next) + if (pd_checkglist(&y->g_pd) && !canvas_isabstraction((t_canvas *)y)) + canvas_dofont((t_canvas *)y, font, xresize, yresize); +} + + /* canvas_menufont calls up a TK dialog which calls this back */ +static void canvas_font(t_canvas *x, t_floatarg font, t_floatarg resize, + t_floatarg whichresize) +{ + t_float realresize, realresx = 1, realresy = 1; + t_canvas *x2 = canvas_getrootfor(x); + if (!resize) realresize = 1; + else + { + if (resize < 20) resize = 20; + if (resize > 500) resize = 500; + realresize = resize * 0.01; + } + if (whichresize != 3) realresx = realresize; + if (whichresize != 2) realresy = realresize; + canvas_dofont(x2, font, realresx, realresy); + sys_defaultfont = font; +} + +void glist_getnextxy(t_glist *gl, int *xpix, int *ypix) +{ + if (EDITOR->canvas_last_glist == gl) + *xpix = EDITOR->canvas_last_glist_x, + *ypix = EDITOR->canvas_last_glist_y; + else *xpix = *ypix = 40; +} + +static void glist_setlastxy(t_glist *gl, int xval, int yval) +{ + EDITOR->canvas_last_glist = gl; + EDITOR->canvas_last_glist_x = xval; + EDITOR->canvas_last_glist_y = yval; +} + + +void g_editor_setup(void) +{ +/* ------------------------ events ---------------------------------- */ + class_addmethod(canvas_class, (t_method)canvas_mouse, gensym("mouse"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_mouseup, gensym("mouseup"), + A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_key, gensym("key"), + A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_motion, gensym("motion"), + A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + +/* ------------------------ menu actions ---------------------------- */ + class_addmethod(canvas_class, (t_method)canvas_menuclose, + gensym("menuclose"), A_DEFFLOAT, 0); + class_addmethod(canvas_class, (t_method)canvas_cut, + gensym("cut"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_copy, + gensym("copy"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_paste, + gensym("paste"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_duplicate, + gensym("duplicate"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_selectall, + gensym("selectall"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_reselect, + gensym("reselect"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_undo, + gensym("undo"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_redo, + gensym("redo"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_tidy, + gensym("tidy"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_texteditor, + gensym("texteditor"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_editmode, + gensym("editmode"), A_DEFFLOAT, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_print, + gensym("print"), A_SYMBOL, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_menufont, + gensym("menufont"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_font, + gensym("font"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_zoom, + gensym("zoom"), A_FLOAT, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_find, + gensym("find"), A_SYMBOL, A_FLOAT, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_find_again, + gensym("findagain"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_find_parent, + gensym("findparent"), A_NULL); + class_addmethod(canvas_class, (t_method)canvas_done_popup, + gensym("done-popup"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_donecanvasdialog, + gensym("donecanvasdialog"), A_GIMME, A_NULL); + class_addmethod(canvas_class, (t_method)glist_arraydialog, + gensym("arraydialog"), A_SYMBOL, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + +/* -------------- connect method used in reading files ------------------ */ + class_addmethod(canvas_class, (t_method)canvas_connect, + gensym("connect"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + + class_addmethod(canvas_class, (t_method)canvas_disconnect, + gensym("disconnect"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); +/* -------------- copy buffer ------------------ */ + EDITOR->copy_binbuf = binbuf_new(); +} + +void canvas_editor_for_class(t_class *c) +{ + class_addmethod(c, (t_method)canvas_mouse, gensym("mouse"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(c, (t_method)canvas_mouseup, gensym("mouseup"), + A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(c, (t_method)canvas_key, gensym("key"), + A_GIMME, A_NULL); + class_addmethod(c, (t_method)canvas_motion, gensym("motion"), + A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + +/* ------------------------ menu actions ---------------------------- */ + class_addmethod(c, (t_method)canvas_menuclose, + gensym("menuclose"), A_DEFFLOAT, 0); + class_addmethod(c, (t_method)canvas_find_parent, + gensym("findparent"), A_NULL); +} + +void g_editor_newpdinstance( void) +{ + EDITOR = getbytes(sizeof(*EDITOR)); +} + +void g_editor_freepdinstance( void) +{ + if (EDITOR->copy_binbuf) + binbuf_free(EDITOR->copy_binbuf); + if (EDITOR->canvas_undo_buf) + { + if (!EDITOR->canvas_undo_fn) + bug("g_editor_freepdinstance"); + else (*EDITOR->canvas_undo_fn) + (EDITOR->canvas_undo_canvas, EDITOR->canvas_undo_buf, UNDO_FREE); + } + if (EDITOR->canvas_findbuf) + binbuf_free(EDITOR->canvas_findbuf); + freebytes(EDITOR, sizeof(*EDITOR)); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_graph.c b/ports/camomile/source/LibPd/pure-data/src/g_graph.c new file mode 100644 index 00000000..a102a417 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_graph.c @@ -0,0 +1,1111 @@ +/* Copyright (c) 1997-2001 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This file deals with the behavior of glists as either "text objects" or +"graphs" inside another glist. LATER move the inlet/outlet code of g_canvas.c +to this file... */ + +#include +#include "m_pd.h" + +#include "g_canvas.h" +#include +#include + +/* ---------------------- forward definitions ----------------- */ + +static void graph_vis(t_gobj *gr, t_glist *unused_glist, int vis); +static void graph_graphrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2); +static void graph_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2); + +/* -------------------- maintaining the list -------------------- */ + +void canvas_drawredrect(t_canvas *x, int doit); + +void glist_add(t_glist *x, t_gobj *y) +{ + t_object *ob; + y->g_next = 0; + if (!x->gl_list) x->gl_list = y; + else + { + t_gobj *y2; + for (y2 = x->gl_list; y2->g_next; y2 = y2->g_next); + y2->g_next = y; + } + if (x->gl_editor && (ob = pd_checkobject(&y->g_pd))) + rtext_new(x, ob); + if (x->gl_editor && x->gl_isgraph && !x->gl_goprect + && pd_checkobject(&y->g_pd)) + { + x->gl_goprect = 1; + canvas_drawredrect(x, 1); + } + if (glist_isvisible(x)) + gobj_vis(y, x, 1); + if (class_isdrawcommand(y->g_pd)) + canvas_redrawallfortemplate(template_findbyname(canvas_makebindsym( + glist_getcanvas(x)->gl_name)), 0); +} + + /* this is to protect against a hairy problem in which deleting + a sub-canvas might delete an inlet on a box, after the box had + been invisible-ized, so that we have to protect against redrawing it! */ +int canvas_setdeleting(t_canvas *x, int flag) +{ + int ret = x->gl_isdeleting; + x->gl_isdeleting = flag; + return (ret); +} + + /* JMZ: emit a closebang message */ +void rtext_freefortext(t_glist *gl, t_text *who); + + /* delete an object from a glist and free it */ +void glist_delete(t_glist *x, t_gobj *y) +{ + t_gobj *g; + t_object *ob; + t_gotfn chkdsp = zgetfn(&y->g_pd, gensym("dsp")); + t_canvas *canvas = glist_getcanvas(x); + t_rtext *rtext = 0; + int drawcommand = class_isdrawcommand(y->g_pd); + int wasdeleting; + + if (pd_class(&y->g_pd) == canvas_class) { + /* JMZ: send a closebang to the canvas */ + canvas_closebang((t_canvas *)y); + } + + wasdeleting = canvas_setdeleting(canvas, 1); + if (x->gl_editor) + { + if (x->gl_editor->e_grab == y) x->gl_editor->e_grab = 0; + if (glist_isselected(x, y)) glist_deselect(x, y); + + /* HACK -- we had phantom outlets not getting erased on the + screen because the canvas_setdeleting() mechanism is too + crude. LATER carefully set up rules for when the rtexts + should exist, so that they stay around until all the + steps of becoming invisible are done. In the meantime, just + zap the inlets and outlets here... */ + if (pd_class(&y->g_pd) == canvas_class) + { + t_glist *gl = (t_glist *)y; + if (gl->gl_isgraph && glist_isvisible(x)) + { + char tag[80]; + sprintf(tag, "graph%lx", (t_int)gl); + glist_eraseiofor(x, &gl->gl_obj, tag); + } + else + { + if (glist_isvisible(x)) + text_eraseborder(&gl->gl_obj, x, + rtext_gettag(glist_findrtext(x, &gl->gl_obj))); + } + } + } + /* if we're a drawing command, erase all scalars now, before deleting + it; we'll redraw them once it's deleted below. */ + if (drawcommand) + canvas_redrawallfortemplate(template_findbyname(canvas_makebindsym( + glist_getcanvas(x)->gl_name)), 2); + gobj_delete(y, x); + if (glist_isvisible(canvas)) + { + gobj_vis(y, x, 0); + } + if (x->gl_editor && (ob = pd_checkobject(&y->g_pd)) && + !(rtext = glist_findrtext(x, ob))) + rtext = rtext_new(x, ob); + if (x->gl_list == y) x->gl_list = y->g_next; + else for (g = x->gl_list; g; g = g->g_next) + if (g->g_next == y) + { + g->g_next = y->g_next; + break; + } + pd_free(&y->g_pd); + if (rtext) + rtext_free(rtext); + if (chkdsp) canvas_update_dsp(); + if (drawcommand) + canvas_redrawallfortemplate(template_findbyname(canvas_makebindsym( + glist_getcanvas(x)->gl_name)), 1); + canvas_setdeleting(canvas, wasdeleting); + x->gl_valid = ++glist_valid; +} + + /* remove every object from a glist. Experimental. */ +void glist_clear(t_glist *x) +{ + t_gobj *y, *y2; + int dspstate = 0, suspended = 0; + t_symbol *dspsym = gensym("dsp"); + while ((y = x->gl_list)) + { + /* to avoid unnecessary DSP resorting, we suspend DSP + only if we hit a patchable object. */ + if (!suspended && pd_checkobject(&y->g_pd) && zgetfn(&y->g_pd, dspsym)) + { + dspstate = canvas_suspend_dsp(); + suspended = 1; + } + /* here's the real deletion. */ + glist_delete(x, y); + } + if (suspended) + canvas_resume_dsp(dspstate); +} + +void glist_retext(t_glist *glist, t_text *y) +{ + t_canvas *c = glist_getcanvas(glist); + /* check that we have built rtexts yet. LATER need a better test. */ + if (glist->gl_editor && glist->gl_editor->e_rtext) + { + t_rtext *rt = glist_findrtext(glist, y); + if (rt) + rtext_retext(rt); + } +} + +void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn, + t_glistkeyfn keyfn, int xpos, int ypos) +{ + t_glist *x2 = glist_getcanvas(x); + if (motionfn) + x2->gl_editor->e_onmotion = MA_PASSOUT; + else x2->gl_editor->e_onmotion = 0; + x2->gl_editor->e_grab = y; + x2->gl_editor->e_motionfn = motionfn; + x2->gl_editor->e_keyfn = keyfn; + x2->gl_editor->e_xwas = xpos; + x2->gl_editor->e_ywas = ypos; +} + +t_canvas *glist_getcanvas(t_glist *x) +{ + while (x->gl_owner && !x->gl_havewindow && x->gl_isgraph) + x = x->gl_owner; + return((t_canvas *)x); +} + +static t_float gobj_getxforsort(t_gobj *g) +{ + if (pd_class(&g->g_pd) == scalar_class) + { + t_float x1, y1; + scalar_getbasexy((t_scalar *)g, &x1, &y1); + return(x1); + } + else return (0); +} + +static t_gobj *glist_merge(t_glist *x, t_gobj *g1, t_gobj *g2) +{ + t_gobj *g = 0, *g9 = 0; + t_float f1 = 0, f2 = 0; + if (g1) + f1 = gobj_getxforsort(g1); + if (g2) + f2 = gobj_getxforsort(g2); + while (1) + { + if (g1) + { + if (g2) + { + if (f1 <= f2) + goto put1; + else goto put2; + } + else goto put1; + } + else if (g2) + goto put2; + else break; + put1: + if (g9) + g9->g_next = g1, g9 = g1; + else g9 = g = g1; + if ((g1 = g1->g_next)) + f1 = gobj_getxforsort(g1); + g9->g_next = 0; + continue; + put2: + if (g9) + g9->g_next = g2, g9 = g2; + else g9 = g = g2; + if ((g2 = g2->g_next)) + f2 = gobj_getxforsort(g2); + g9->g_next = 0; + continue; + } + return (g); +} + +static t_gobj *glist_dosort(t_glist *x, + t_gobj *g, int nitems) +{ + if (nitems < 2) + return (g); + else + { + int n1 = nitems/2, n2 = nitems - n1, i; + t_gobj *g2, *g3; + for (g2 = g, i = n1-1; i--; g2 = g2->g_next) + ; + g3 = g2->g_next; + g2->g_next = 0; + g = glist_dosort(x, g, n1); + g3 = glist_dosort(x, g3, n2); + return (glist_merge(x, g, g3)); + } +} + +void glist_sort(t_glist *x) +{ + int nitems = 0, foo = 0; + t_float lastx = -1e37; + t_gobj *g; + for (g = x->gl_list; g; g = g->g_next) + { + t_float x1 = gobj_getxforsort(g); + if (x1 < lastx) + foo = 1; + lastx = x1; + nitems++; + } + if (foo) + x->gl_list = glist_dosort(x, x->gl_list, nitems); +} + +/* --------------- inlets and outlets ----------- */ + + +t_inlet *canvas_addinlet(t_canvas *x, t_pd *who, t_symbol *s) +{ + t_inlet *ip = inlet_new(&x->gl_obj, who, s, 0); + if (!x->gl_loading && x->gl_owner && glist_isvisible(x->gl_owner)) + { + gobj_vis(&x->gl_gobj, x->gl_owner, 0); + gobj_vis(&x->gl_gobj, x->gl_owner, 1); + canvas_fixlinesfor(x->gl_owner, &x->gl_obj); + } + if (!x->gl_loading) canvas_resortinlets(x); + return (ip); +} + +void canvas_rminlet(t_canvas *x, t_inlet *ip) +{ + t_canvas *owner = x->gl_owner; + int redraw = (owner && glist_isvisible(owner) && (!owner->gl_isdeleting) + && glist_istoplevel(owner)); + + if (owner) canvas_deletelinesforio(owner, &x->gl_obj, ip, 0); + if (redraw) + gobj_vis(&x->gl_gobj, x->gl_owner, 0); + inlet_free(ip); + if (redraw) + { + gobj_vis(&x->gl_gobj, x->gl_owner, 1); + canvas_fixlinesfor(x->gl_owner, &x->gl_obj); + } +} + +extern t_inlet *vinlet_getit(t_pd *x); +extern void obj_moveinletfirst(t_object *x, t_inlet *i); + +void canvas_resortinlets(t_canvas *x) +{ + int ninlets = 0, i, j, xmax; + t_gobj *y, **vec, **vp, **maxp; + + for (ninlets = 0, y = x->gl_list; y; y = y->g_next) + if (pd_class(&y->g_pd) == vinlet_class) ninlets++; + + if (ninlets < 2) return; + + vec = (t_gobj **)getbytes(ninlets * sizeof(*vec)); + + for (y = x->gl_list, vp = vec; y; y = y->g_next) + if (pd_class(&y->g_pd) == vinlet_class) *vp++ = y; + + for (i = ninlets; i--;) + { + t_inlet *ip; + for (vp = vec, xmax = -0x7fffffff, maxp = 0, j = ninlets; + j--; vp++) + { + int x1, y1, x2, y2; + t_gobj *g = *vp; + if (!g) continue; + gobj_getrect(g, x, &x1, &y1, &x2, &y2); + if (x1 > xmax) xmax = x1, maxp = vp; + } + if (!maxp) break; + y = *maxp; + *maxp = 0; + ip = vinlet_getit(&y->g_pd); + + obj_moveinletfirst(&x->gl_obj, ip); + } + freebytes(vec, ninlets * sizeof(*vec)); + if (x->gl_owner && glist_isvisible(x->gl_owner)) + canvas_fixlinesfor(x->gl_owner, &x->gl_obj); +} + +t_outlet *canvas_addoutlet(t_canvas *x, t_pd *who, t_symbol *s) +{ + t_outlet *op = outlet_new(&x->gl_obj, s); + if (!x->gl_loading && x->gl_owner && glist_isvisible(x->gl_owner)) + { + gobj_vis(&x->gl_gobj, x->gl_owner, 0); + gobj_vis(&x->gl_gobj, x->gl_owner, 1); + canvas_fixlinesfor(x->gl_owner, &x->gl_obj); + } + if (!x->gl_loading) canvas_resortoutlets(x); + return (op); +} + +void canvas_rmoutlet(t_canvas *x, t_outlet *op) +{ + t_canvas *owner = x->gl_owner; + int redraw = (owner && glist_isvisible(owner) && (!owner->gl_isdeleting) + && glist_istoplevel(owner)); + + if (owner) canvas_deletelinesforio(owner, &x->gl_obj, 0, op); + if (redraw) + gobj_vis(&x->gl_gobj, x->gl_owner, 0); + + outlet_free(op); + if (redraw) + { + gobj_vis(&x->gl_gobj, x->gl_owner, 1); + canvas_fixlinesfor(x->gl_owner, &x->gl_obj); + } +} + +extern t_outlet *voutlet_getit(t_pd *x); +extern void obj_moveoutletfirst(t_object *x, t_outlet *i); + +void canvas_resortoutlets(t_canvas *x) +{ + int noutlets = 0, i, j, xmax; + t_gobj *y, **vec, **vp, **maxp; + + for (noutlets = 0, y = x->gl_list; y; y = y->g_next) + if (pd_class(&y->g_pd) == voutlet_class) noutlets++; + + if (noutlets < 2) return; + + vec = (t_gobj **)getbytes(noutlets * sizeof(*vec)); + + for (y = x->gl_list, vp = vec; y; y = y->g_next) + if (pd_class(&y->g_pd) == voutlet_class) *vp++ = y; + + for (i = noutlets; i--;) + { + t_outlet *ip; + for (vp = vec, xmax = -0x7fffffff, maxp = 0, j = noutlets; + j--; vp++) + { + int x1, y1, x2, y2; + t_gobj *g = *vp; + if (!g) continue; + gobj_getrect(g, x, &x1, &y1, &x2, &y2); + if (x1 > xmax) xmax = x1, maxp = vp; + } + if (!maxp) break; + y = *maxp; + *maxp = 0; + ip = voutlet_getit(&y->g_pd); + + obj_moveoutletfirst(&x->gl_obj, ip); + } + freebytes(vec, noutlets * sizeof(*vec)); + if (x->gl_owner && glist_isvisible(x->gl_owner)) + canvas_fixlinesfor(x->gl_owner, &x->gl_obj); +} + +/* ----------calculating coordinates and controlling appearance --------- */ + + +static void graph_bounds(t_glist *x, t_floatarg x1, t_floatarg y1, + t_floatarg x2, t_floatarg y2) +{ + x->gl_x1 = x1; + x->gl_x2 = x2; + x->gl_y1 = y1; + x->gl_y2 = y2; + if (x->gl_x2 == x->gl_x1 || + x->gl_y2 == x->gl_y1) + { + error("graph: empty bounds rectangle"); + x1 = y1 = 0; + x2 = y2 = 1; + } + glist_redraw(x); +} + +static void graph_xticks(t_glist *x, + t_floatarg point, t_floatarg inc, t_floatarg f) +{ + x->gl_xtick.k_point = point; + x->gl_xtick.k_inc = inc; + x->gl_xtick.k_lperb = f; + glist_redraw(x); +} + +static void graph_yticks(t_glist *x, + t_floatarg point, t_floatarg inc, t_floatarg f) +{ + x->gl_ytick.k_point = point; + x->gl_ytick.k_inc = inc; + x->gl_ytick.k_lperb = f; + glist_redraw(x); +} + +static void graph_xlabel(t_glist *x, t_symbol *s, int argc, t_atom *argv) +{ + int i; + if (argc < 1) error("graph_xlabel: no y value given"); + else + { + x->gl_xlabely = atom_getfloat(argv); + argv++; argc--; + x->gl_xlabel = (t_symbol **)t_resizebytes(x->gl_xlabel, + x->gl_nxlabels * sizeof (t_symbol *), argc * sizeof (t_symbol *)); + x->gl_nxlabels = argc; + for (i = 0; i < argc; i++) x->gl_xlabel[i] = atom_gensym(&argv[i]); + } + glist_redraw(x); +} + +static void graph_ylabel(t_glist *x, t_symbol *s, int argc, t_atom *argv) +{ + int i; + if (argc < 1) error("graph_ylabel: no x value given"); + else + { + x->gl_ylabelx = atom_getfloat(argv); + argv++; argc--; + x->gl_ylabel = (t_symbol **)t_resizebytes(x->gl_ylabel, + x->gl_nylabels * sizeof (t_symbol *), argc * sizeof (t_symbol *)); + x->gl_nylabels = argc; + for (i = 0; i < argc; i++) x->gl_ylabel[i] = atom_gensym(&argv[i]); + } + glist_redraw(x); +} + +/****** routines to convert pixels to X or Y value and vice versa ******/ + + /* convert an x pixel value to an x coordinate value */ +t_float glist_pixelstox(t_glist *x, t_float xpix) +{ + /* if we appear as a text box on parent, our range in our + coordinates (x1, etc.) specifies the coordinate range + of a one-pixel square at top left of the window. */ + if (!x->gl_isgraph) + return (x->gl_x1 + (x->gl_x2 - x->gl_x1) * xpix); + + /* if we're a graph when shown on parent, but own our own + window right now, our range in our coordinates (x1, etc.) is spread + over the visible window size, given by screenx1, etc. */ + else if (x->gl_isgraph && x->gl_havewindow) + return (x->gl_x1 + (x->gl_x2 - x->gl_x1) * + (xpix) / (x->gl_screenx2 - x->gl_screenx1)); + + /* otherwise, we appear in a graph within a parent glist, + so get our screen rectangle on parent and transform. */ + else + { + int x1, y1, x2, y2; + if (!x->gl_owner) + bug("glist_pixelstox"); + graph_graphrect(&x->gl_gobj, x->gl_owner, &x1, &y1, &x2, &y2); + return (x->gl_x1 + (x->gl_x2 - x->gl_x1) * + (xpix - x1) / (x2 - x1)); + } +} + +t_float glist_pixelstoy(t_glist *x, t_float ypix) +{ + if (!x->gl_isgraph) + return (x->gl_y1 + (x->gl_y2 - x->gl_y1) * ypix); + else if (x->gl_isgraph && x->gl_havewindow) + return (x->gl_y1 + (x->gl_y2 - x->gl_y1) * + (ypix) / (x->gl_screeny2 - x->gl_screeny1)); + else + { + int x1, y1, x2, y2; + if (!x->gl_owner) + bug("glist_pixelstox"); + graph_graphrect(&x->gl_gobj, x->gl_owner, &x1, &y1, &x2, &y2); + return (x->gl_y1 + (x->gl_y2 - x->gl_y1) * + (ypix - y1) / (y2 - y1)); + } +} + + /* convert an x coordinate value to an x pixel location in window */ +t_float glist_xtopixels(t_glist *x, t_float xval) +{ + if (!x->gl_isgraph) + return ((xval - x->gl_x1) / (x->gl_x2 - x->gl_x1)); + else if (x->gl_isgraph && x->gl_havewindow) + return (x->gl_screenx2 - x->gl_screenx1) * + (xval - x->gl_x1) / (x->gl_x2 - x->gl_x1); + else + { + int x1, y1, x2, y2; + if (!x->gl_owner) + bug("glist_pixelstox"); + graph_graphrect(&x->gl_gobj, x->gl_owner, &x1, &y1, &x2, &y2); + return (x1 + (x2 - x1) * (xval - x->gl_x1) / (x->gl_x2 - x->gl_x1)); + } +} + +t_float glist_ytopixels(t_glist *x, t_float yval) +{ + if (!x->gl_isgraph) + return ((yval - x->gl_y1) / (x->gl_y2 - x->gl_y1)); + else if (x->gl_isgraph && x->gl_havewindow) + return (x->gl_screeny2 - x->gl_screeny1) * + (yval - x->gl_y1) / (x->gl_y2 - x->gl_y1); + else + { + int x1, y1, x2, y2; + if (!x->gl_owner) + bug("glist_pixelstox"); + graph_graphrect(&x->gl_gobj, x->gl_owner, &x1, &y1, &x2, &y2); + return (y1 + (y2 - y1) * (yval - x->gl_y1) / (x->gl_y2 - x->gl_y1)); + } +} + + /* convert an X screen distance to an X coordinate increment. + This is terribly inefficient; + but probably not a big enough CPU hog to warrant optimizing. */ +t_float glist_dpixtodx(t_glist *x, t_float dxpix) +{ + return (dxpix * (glist_pixelstox(x, 1) - glist_pixelstox(x, 0))); +} + +t_float glist_dpixtody(t_glist *x, t_float dypix) +{ + return (dypix * (glist_pixelstoy(x, 1) - glist_pixelstoy(x, 0))); +} + + /* get the window location in pixels of a "text" object. The + object's x and y positions are in pixels when the glist they're + in is toplevel. Otherwise, if it's a new-style graph-on-parent + (so gl_goprect is set) we use the offset into the framing subrectangle + as an offset into the parent rectangle. Finally, it might be an old, + proportional-style GOP. In this case we do a coordinate transformation. */ +int text_xpix(t_text *x, t_glist *glist) +{ + if (glist->gl_havewindow || !glist->gl_isgraph) + return (x->te_xpix); + else if (glist->gl_goprect) + return (glist_xtopixels(glist, glist->gl_x1) + + x->te_xpix - glist->gl_xmargin); + else return (glist_xtopixels(glist, + glist->gl_x1 + (glist->gl_x2 - glist->gl_x1) * + x->te_xpix / (glist->gl_screenx2 - glist->gl_screenx1))); +} + +int text_ypix(t_text *x, t_glist *glist) +{ + if (glist->gl_havewindow || !glist->gl_isgraph) + return (x->te_ypix); + else if (glist->gl_goprect) + return (glist_ytopixels(glist, glist->gl_y1) + + x->te_ypix - glist->gl_ymargin); + else return (glist_ytopixels(glist, + glist->gl_y1 + (glist->gl_y2 - glist->gl_y1) * + x->te_ypix / (glist->gl_screeny2 - glist->gl_screeny1))); +} + + /* redraw all the items in a glist. We construe this to mean + redrawing in its own window and on parent, as needed in each case. + This is too conservative -- for instance, when you draw an "open" + rectangle on the parent, you shouldn't have to redraw the window! */ +void glist_redraw(t_glist *x) +{ + if (glist_isvisible(x)) + { + /* LATER fix the graph_vis() code to handle both cases */ + if (glist_istoplevel(x)) + { + t_gobj *g; + t_linetraverser t; + t_outconnect *oc; + for (g = x->gl_list; g; g = g->g_next) + { + gobj_vis(g, x, 0); + gobj_vis(g, x, 1); + } + /* redraw all the lines */ + linetraverser_start(&t, x); + while ((oc = linetraverser_next(&t))) + sys_vgui(".x%lx.c coords l%lx %d %d %d %d\n", + glist_getcanvas(x), oc, + t.tr_lx1, t.tr_ly1, t.tr_lx2, t.tr_ly2); + canvas_drawredrect(x, 0); + if (x->gl_goprect) + { + canvas_drawredrect(x, 1); + } + } + if (x->gl_owner && glist_isvisible(x->gl_owner)) + { + graph_vis(&x->gl_gobj, x->gl_owner, 0); + graph_vis(&x->gl_gobj, x->gl_owner, 1); + } + } +} + +/* --------------------------- widget behavior ------------------- */ + +int garray_getname(t_garray *x, t_symbol **namep); + + + /* Note that some code in here would also be useful for drawing + graph decorations in toplevels... */ +static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis) +{ + t_glist *x = (t_glist *)gr; + char tag[50]; + t_gobj *g; + int x1, y1, x2, y2; + /* ordinary subpatches: just act like a text object */ + if (!x->gl_isgraph) + { + text_widgetbehavior.w_visfn(gr, parent_glist, vis); + return; + } + + if (vis && canvas_showtext(x)) + rtext_draw(glist_findrtext(parent_glist, &x->gl_obj)); + graph_getrect(gr, parent_glist, &x1, &y1, &x2, &y2); + if (!vis) + rtext_erase(glist_findrtext(parent_glist, &x->gl_obj)); + + sprintf(tag, "graph%lx", (t_int)x); + if (vis) + glist_drawiofor(parent_glist, &x->gl_obj, 1, + tag, x1, y1, x2, y2); + else glist_eraseiofor(parent_glist, &x->gl_obj, tag); + /* if we look like a graph but have been moved to a toplevel, + just show the bounding rectangle */ + if (x->gl_havewindow) + { + if (vis) + { + sys_vgui(".x%lx.c create polygon %d %d %d %d %d %d %d %d %d %d " + "-width %d -fill #c0c0c0 -joinstyle miter -tags [list %s graph]\n", + glist_getcanvas(x->gl_owner), + x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, glist_getzoom(x), tag); + } + else + { + sys_vgui(".x%lx.c delete %s\n", + glist_getcanvas(x->gl_owner), tag); + } + return; + } + /* otherwise draw (or erase) us as a graph inside another glist. */ + if (vis) + { + int i; + t_float f; + t_gobj *g; + t_symbol *arrayname; + t_garray *ga; + char *ylabelanchor = + (x->gl_ylabelx > 0.5*(x->gl_x1 + x->gl_x2) ? "w" : "e"); + char *xlabelanchor = + (x->gl_xlabely > 0.5*(x->gl_y1 + x->gl_y2) ? "s" : "n"); + int fs = sys_hostfontsize(glist_getfont(x), glist_getzoom(x)); + + /* draw a rectangle around the graph */ + sys_vgui(".x%lx.c create line %d %d %d %d %d %d %d %d %d %d " + "-width %d -capstyle projecting -tags [list %s graph]\n", + glist_getcanvas(x->gl_owner), + x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, glist_getzoom(x), tag); + + /* if there's just one "garray" in the graph, write its name + along the top */ + for (i = (y1 < y2 ? y1 : y2)-1, g = x->gl_list; g; g = g->g_next) + if (g->g_pd == garray_class && + !garray_getname((t_garray *)g, &arrayname)) + { + i -= glist_fontheight(x); + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor nw " + "-font {{%s} -%d %s} -tags [list %s label graph]\n", + (long)glist_getcanvas(x), x1, i, + arrayname->s_name, sys_font, + fs, sys_fontweight, tag); + } + + /* draw ticks on horizontal borders. If lperb field is + zero, this is disabled. */ + if (x->gl_xtick.k_lperb) + { + t_float upix, lpix; + if (y2 < y1) + upix = y1, lpix = y2; + else upix = y2, lpix = y1; + for (i = 0, f = x->gl_xtick.k_point; + f < 0.99 * x->gl_x2 + 0.01*x->gl_x1; i++, + f += x->gl_xtick.k_inc) + { + int tickpix = (i % x->gl_xtick.k_lperb ? 2 : 4); + sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags [list %s graph]\n", + glist_getcanvas(x->gl_owner), + (int)glist_xtopixels(x, f), (int)upix, + (int)glist_xtopixels(x, f), (int)upix - tickpix, glist_getzoom(x), tag); + sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags [list %s graph]\n", + glist_getcanvas(x->gl_owner), + (int)glist_xtopixels(x, f), (int)lpix, + (int)glist_xtopixels(x, f), (int)lpix + tickpix, glist_getzoom(x), tag); + } + for (i = 1, f = x->gl_xtick.k_point - x->gl_xtick.k_inc; + f > 0.99 * x->gl_x1 + 0.01*x->gl_x2; + i++, f -= x->gl_xtick.k_inc) + { + int tickpix = (i % x->gl_xtick.k_lperb ? 2 : 4); + sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags [list %s graph]\n", + glist_getcanvas(x->gl_owner), + (int)glist_xtopixels(x, f), (int)upix, + (int)glist_xtopixels(x, f), (int)upix - tickpix, glist_getzoom(x), tag); + sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags [list %s graph]\n", + glist_getcanvas(x->gl_owner), + (int)glist_xtopixels(x, f), (int)lpix, + (int)glist_xtopixels(x, f), (int)lpix + tickpix, glist_getzoom(x), tag); + } + } + + /* draw ticks in vertical borders*/ + if (x->gl_ytick.k_lperb) + { + t_float ubound, lbound; + if (x->gl_y2 < x->gl_y1) + ubound = x->gl_y1, lbound = x->gl_y2; + else ubound = x->gl_y2, lbound = x->gl_y1; + for (i = 0, f = x->gl_ytick.k_point; + f < 0.99 * ubound + 0.01 * lbound; + i++, f += x->gl_ytick.k_inc) + { + int tickpix = (i % x->gl_ytick.k_lperb ? 2 : 4); + sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags [list %s graph]\n", + glist_getcanvas(x->gl_owner), + x1, (int)glist_ytopixels(x, f), + x1 + tickpix, (int)glist_ytopixels(x, f), glist_getzoom(x), tag); + sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags [list %s graph]\n", + glist_getcanvas(x->gl_owner), + x2, (int)glist_ytopixels(x, f), + x2 - tickpix, (int)glist_ytopixels(x, f), glist_getzoom(x), tag); + } + for (i = 1, f = x->gl_ytick.k_point - x->gl_ytick.k_inc; + f > 0.99 * lbound + 0.01 * ubound; + i++, f -= x->gl_ytick.k_inc) + { + int tickpix = (i % x->gl_ytick.k_lperb ? 2 : 4); + sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags [list %s graph]\n", + glist_getcanvas(x->gl_owner), + x1, (int)glist_ytopixels(x, f), + x1 + tickpix, (int)glist_ytopixels(x, f), glist_getzoom(x), tag); + sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags [list %s graph]\n", + glist_getcanvas(x->gl_owner), + x2, (int)glist_ytopixels(x, f), + x2 - tickpix, (int)glist_ytopixels(x, f), glist_getzoom(x), tag); + } + } + /* draw x labels */ + for (i = 0; i < x->gl_nxlabels; i++) + sys_vgui(".x%lx.c create text %d %d -text {%s} -font {{%s} -%d %s} " + "-anchor %s -tags [list %s label graph]\n", + glist_getcanvas(x), + (int)glist_xtopixels(x, atof(x->gl_xlabel[i]->s_name)), + (int)glist_ytopixels(x, x->gl_xlabely), + x->gl_xlabel[i]->s_name, sys_font, + fs, sys_fontweight, xlabelanchor, tag); + + /* draw y labels */ + for (i = 0; i < x->gl_nylabels; i++) + sys_vgui(".x%lx.c create text %d %d -text {%s} -font {{%s} -%d %s} " + "-anchor %s -tags [list %s label graph]\n", + glist_getcanvas(x), + (int)glist_xtopixels(x, x->gl_ylabelx), + (int)glist_ytopixels(x, atof(x->gl_ylabel[i]->s_name)), + x->gl_ylabel[i]->s_name, sys_font, + fs, sys_fontweight, ylabelanchor, tag); + + /* draw contents of graph as glist */ + for (g = x->gl_list; g; g = g->g_next) + gobj_vis(g, x, 1); + } + else + { + sys_vgui(".x%lx.c delete %s\n", + glist_getcanvas(x->gl_owner), tag); + for (g = x->gl_list; g; g = g->g_next) + gobj_vis(g, x, 0); + } +} + + /* get the graph's rectangle, not counting extra swelling for controls + to keep them inside the graph. This is the "logical" pixel size. */ + +static void graph_graphrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_glist *x = (t_glist *)z; + int x1 = text_xpix(&x->gl_obj, glist); + int y1 = text_ypix(&x->gl_obj, glist); + int x2, y2; + x2 = x1 + x->gl_pixwidth; + y2 = y1 + x->gl_pixheight; + + *xp1 = x1; + *yp1 = y1; + *xp2 = x2; + *yp2 = y2; +} + + /* get the rectangle, enlarged to contain all the "contents" -- + meaning their formal bounds rectangles. */ +static void graph_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + int x1 = 0x7fffffff, y1 = 0x7fffffff, x2 = -0x7fffffff, y2 = -0x7fffffff; + t_glist *x = (t_glist *)z; + if (x->gl_isgraph) + { + int hadwindow; + t_gobj *g; + t_text *ob; + int x21, y21, x22, y22; + + graph_graphrect(z, glist, &x1, &y1, &x2, &y2); + if (canvas_showtext(x)) + { + text_widgetbehavior.w_getrectfn(z, glist, &x21, &y21, &x22, &y22); + if (x22 > x2) + x2 = x22; + if (y22 > y2) + y2 = y22; + } + if (!x->gl_goprect) + { + /* expand the rectangle to fit in text objects; this applies only + to the old (0.37) graph-on-parent behavior. */ + /* lie about whether we have our own window to affect gobj_getrect + calls below. */ + hadwindow = x->gl_havewindow; + x->gl_havewindow = 0; + for (g = x->gl_list; g; g = g->g_next) + { + /* don't do this for arrays, just let them hang outside the + box. And ignore "text" objects which aren't shown on + parent */ + if (pd_class(&g->g_pd) == garray_class || + pd_checkobject(&g->g_pd)) + continue; + gobj_getrect(g, x, &x21, &y21, &x22, &y22); + if (x22 > x2) + x2 = x22; + if (y22 > y2) + y2 = y22; + } + x->gl_havewindow = hadwindow; + } + } + else text_widgetbehavior.w_getrectfn(z, glist, &x1, &y1, &x2, &y2); + *xp1 = x1; + *yp1 = y1; + *xp2 = x2; + *yp2 = y2; +} + +static void graph_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_glist *x = (t_glist *)z; + if (!x->gl_isgraph) + text_widgetbehavior.w_displacefn(z, glist, dx, dy); + else + { + x->gl_obj.te_xpix += dx; + x->gl_obj.te_ypix += dy; + glist_redraw(x); + canvas_fixlinesfor(glist, &x->gl_obj); + } +} + +static void graph_select(t_gobj *z, t_glist *glist, int state) +{ + t_glist *x = (t_glist *)z; + if (!x->gl_isgraph) + text_widgetbehavior.w_selectfn(z, glist, state); + else + { + t_rtext *y = glist_findrtext(glist, &x->gl_obj); + if (canvas_showtext(x)) + rtext_select(y, state); + sys_vgui(".x%lx.c itemconfigure %sR -fill %s\n", glist, + rtext_gettag(y), (state? "blue" : "black")); + sys_vgui(".x%lx.c itemconfigure graph%lx -fill %s\n", + glist_getcanvas(glist), z, (state? "blue" : "black")); + } +} + +static void graph_activate(t_gobj *z, t_glist *glist, int state) +{ + t_glist *x = (t_glist *)z; + if (canvas_showtext(x)) + text_widgetbehavior.w_activatefn(z, glist, state); +} + +static void graph_delete(t_gobj *z, t_glist *glist) +{ + t_glist *x = (t_glist *)z; + t_gobj *y; + while ((y = x->gl_list)) + glist_delete(x, y); + if (glist_isvisible(x)) + text_widgetbehavior.w_deletefn(z, glist); + /* if we have connections to the actual 'canvas' object, zap + them as well (e.g., array or scalar objects that are implemented + as canvases with "real" inlets). Connections to ordinary canvas + in/outlets already got zapped when we cleared the contents above */ + canvas_deletelinesfor(glist, &x->gl_obj); +} + +static void graph_motion(void *z, t_floatarg dx, t_floatarg dy) +{ + t_glist *x = (t_glist *)z; + t_float newxpix = THISGUI->i_graph_lastxpix + dx, + newypix = THISGUI->i_graph_lastypix + dy; + t_garray *a = (t_garray *)(x->gl_list); + int oldx = 0.5 + glist_pixelstox(x, THISGUI->i_graph_lastxpix); + int newx = 0.5 + glist_pixelstox(x, newxpix); + t_word *vec; + int nelem, i; + t_float oldy = glist_pixelstoy(x, THISGUI->i_graph_lastypix); + t_float newy = glist_pixelstoy(x, newypix); + THISGUI->i_graph_lastxpix = newxpix; + THISGUI->i_graph_lastypix = newypix; + /* verify that the array is OK */ + if (!a || pd_class((t_pd *)a) != garray_class) + return; + if (!garray_getfloatwords(a, &nelem, &vec)) + return; + if (oldx < 0) oldx = 0; + if (oldx >= nelem) + oldx = nelem - 1; + if (newx < 0) newx = 0; + if (newx >= nelem) + newx = nelem - 1; + if (oldx < newx - 1) + { + for (i = oldx + 1; i <= newx; i++) + vec[i].w_float = newy + (oldy - newy) * + ((t_float)(newx - i))/(t_float)(newx - oldx); + } + else if (oldx > newx + 1) + { + for (i = oldx - 1; i >= newx; i--) + vec[i].w_float = newy + (oldy - newy) * + ((t_float)(newx - i))/(t_float)(newx - oldx); + } + else vec[newx].w_float = newy; + garray_redraw(a); +} + +static int graph_click(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_glist *x = (t_glist *)z; + t_gobj *y; + int clickreturned = 0; + if (!x->gl_isgraph) + return (text_widgetbehavior.w_clickfn(z, glist, + xpix, ypix, shift, alt, dbl, doit)); + else if (x->gl_havewindow) + return (0); + else + { + for (y = x->gl_list; y; y = y->g_next) + { + int x1, y1, x2, y2; + /* check if the object wants to be clicked */ + if (canvas_hitbox(x, y, xpix, ypix, &x1, &y1, &x2, &y2) + && (clickreturned = gobj_click(y, x, xpix, ypix, + shift, alt, 0, doit))) + break; + } + if (!doit) + { + if (y) + canvas_setcursor(glist_getcanvas(x), clickreturned); + else canvas_setcursor(glist_getcanvas(x), CURSOR_RUNMODE_NOTHING); + } + return (clickreturned); + } +} + +const t_widgetbehavior graph_widgetbehavior = +{ + graph_getrect, + graph_displace, + graph_select, + graph_activate, + graph_delete, + graph_vis, + graph_click, +}; + + /* find the graph most recently added to this glist; + if none exists, return 0. */ + +t_glist *glist_findgraph(t_glist *x) +{ + t_gobj *y = 0, *z; + for (z = x->gl_list; z; z = z->g_next) + if (pd_class(&z->g_pd) == canvas_class && ((t_glist *)z)->gl_isgraph) + y = z; + return ((t_glist *)y); +} + +extern void canvas_menuarray(t_glist *canvas); + +void g_graph_setup_class(t_class *c) +{ + class_setwidget(c, &graph_widgetbehavior); + class_addmethod(c, (t_method)graph_bounds, gensym("bounds"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(c, (t_method)graph_xticks, gensym("xticks"), + A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(c, (t_method)graph_xlabel, gensym("xlabel"), + A_GIMME, 0); + class_addmethod(c, (t_method)graph_yticks, gensym("yticks"), + A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(c, (t_method)graph_ylabel, gensym("ylabel"), + A_GIMME, 0); + class_addmethod(c, (t_method)graph_array, gensym("array"), + A_SYMBOL, A_FLOAT, A_SYMBOL, A_DEFFLOAT, A_NULL); + class_addmethod(c, (t_method)canvas_menuarray, + gensym("menuarray"), A_NULL); + class_addmethod(c, (t_method)glist_sort, + gensym("sort"), A_NULL); +} + +void g_graph_setup(void) +{ + g_graph_setup_class(canvas_class); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_guiconnect.c b/ports/camomile/source/LibPd/pure-data/src/g_guiconnect.c new file mode 100644 index 00000000..2b4db785 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_guiconnect.c @@ -0,0 +1,97 @@ +/* Copyright (c) 1997-2000 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* a thing to forward messages from the GUI, dealing with race conditions +in which the "target" gets deleted while the GUI is sending it something. + +See also the gfxstub object that doesn't oblige the owner to keep a pointer +around (so is better suited to one-off dialogs) +*/ + +#include "m_pd.h" +#include "g_canvas.h" + +struct _guiconnect +{ + t_object x_obj; + t_pd *x_who; + t_symbol *x_sym; + t_clock *x_clock; +}; + +static t_class *guiconnect_class; + +t_guiconnect *guiconnect_new(t_pd *who, t_symbol *sym) +{ + t_guiconnect *x = (t_guiconnect *)pd_new(guiconnect_class); + x->x_who = who; + x->x_sym = sym; + pd_bind(&x->x_obj.ob_pd, sym); + return (x); +} + + /* cleanup routine; delete any resources we have */ +static void guiconnect_free(t_guiconnect *x) +{ + if (x->x_sym) + pd_unbind(&x->x_obj.ob_pd, x->x_sym); + if (x->x_clock) + clock_free(x->x_clock); +} + + /* this is called when the clock times out to indicate the GUI should + be gone by now. */ +static void guiconnect_tick(t_guiconnect *x) +{ + pd_free(&x->x_obj.ob_pd); +} + + /* the target calls this to disconnect. If the gui has "signed off" + we're ready to delete the object; otherwise we wait either for signoff + or for a timeout. */ +void guiconnect_notarget(t_guiconnect *x, double timedelay) +{ + if (!x->x_sym) + pd_free(&x->x_obj.ob_pd); + else + { + x->x_who = 0; + if (timedelay > 0) + { + x->x_clock = clock_new(x, (t_method)guiconnect_tick); + clock_delay(x->x_clock, timedelay); + } + } +} + + /* the GUI calls this to send messages to the target. */ +static void guiconnect_anything(t_guiconnect *x, + t_symbol *s, int ac, t_atom *av) +{ + if (x->x_who) + typedmess(x->x_who, s, ac, av); +} + + /* the GUI calls this when it disappears. (If there's any chance the + GUI will fail to do this, the "target", when it signs off, should specify + a timeout after which the guiconnect will disappear.) */ +static void guiconnect_signoff(t_guiconnect *x) +{ + if (!x->x_who) + pd_free(&x->x_obj.ob_pd); + else + { + pd_unbind(&x->x_obj.ob_pd, x->x_sym); + x->x_sym = 0; + } +} + +void g_guiconnect_setup(void) +{ + guiconnect_class = class_new(gensym("guiconnect"), 0, + (t_method)guiconnect_free, sizeof(t_guiconnect), CLASS_PD, 0); + class_addanything(guiconnect_class, guiconnect_anything); + class_addmethod(guiconnect_class, (t_method)guiconnect_signoff, + gensym("signoff"), 0); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_hdial.c b/ports/camomile/source/LibPd/pure-data/src/g_hdial.c new file mode 100644 index 00000000..b17dc1fa --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_hdial.c @@ -0,0 +1,775 @@ +/* Copyright (c) 1997-1999 Miller Puckette. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */ +/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */ + +/* name change to hradio by MSP and changed to +put out a "float" as in sliders, toggles, etc. */ + +#include +#include +#include +#include +#include "m_pd.h" +#include "g_canvas.h" + +#include "g_all_guis.h" +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +/* ------------- hdl gui-horizontal dial ---------------------- */ + +t_widgetbehavior hradio_widgetbehavior; +static t_class *hradio_class, *hradio_old_class; + +/* widget helper functions */ + +void hradio_draw_update(t_gobj *client, t_glist *glist) +{ + t_hradio *x = (t_hradio *)client; + if(glist_isvisible(glist)) + { + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%06x -outline #%06x\n", + canvas, x, x->x_drawn, + x->x_gui.x_bcol, x->x_gui.x_bcol); + sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%06x -outline #%06x\n", + canvas, x, x->x_on, + x->x_gui.x_fcol, x->x_gui.x_fcol); + x->x_drawn = x->x_on; + } +} + +void hradio_draw_new(t_hradio *x, t_glist *glist) +{ + int n = x->x_number, i, dx = x->x_gui.x_w, s4 = dx / 4; + int yy11 = text_ypix(&x->x_gui.x_obj, glist), yy12 = yy11 + dx; + int yy21 = yy11 + s4, yy22 = yy12 - s4; + int xx11b = text_xpix(&x->x_gui.x_obj, glist), xx11 = xx11b, xx21 = xx11b + s4; + int xx22 = xx11b + dx - s4; + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + for(i = 0; i < n; i++) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -fill #%06x -tags %lxBASE%d\n", + canvas, xx11, yy11, xx11 + dx, yy12, IEMGUI_ZOOM(x), + x->x_gui.x_bcol, x, i); + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%06x -outline #%06x -tags %lxBUT%d\n", + canvas, xx21, yy21, xx22, yy22, + (x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol, + (x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol, x, i); + xx11 += dx; + xx21 += dx; + xx22 += dx; + x->x_drawn = x->x_on; + } + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n", + canvas, + xx11b, yy12 + IEMGUI_ZOOM(x) - ioh, + xx11b + iow, yy12, + x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n", + canvas, + xx11b, yy11, + xx11b + iow, yy11 - IEMGUI_ZOOM(x) + ioh, + x, 0); + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w -font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n", + canvas, xx11b + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + yy11 + x->x_gui.x_ldy * IEMGUI_ZOOM(x), + (strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""), + x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + x->x_gui.x_lcol, x); +} + +void hradio_draw_move(t_hradio *x, t_glist *glist) +{ + int n = x->x_number, i, dx = x->x_gui.x_w, s4 = dx / 4; + int yy11 = text_ypix(&x->x_gui.x_obj, glist), yy12 = yy11 + dx; + int yy21 = yy11 + s4, yy22 = yy12 - s4; + int xx11b = text_xpix(&x->x_gui.x_obj, glist), xx11 = xx11b, xx21 = xx11b + s4; + int xx22 = xx11b + dx - s4; + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + xx11 = xx11b; + xx21 = xx11b + s4; + xx22 = xx11b + dx - s4; + for(i = 0; i < n; i++) + { + sys_vgui(".x%lx.c coords %lxBASE%d %d %d %d %d\n", + canvas, x, i, xx11, yy11, xx11 + dx, yy12); + sys_vgui(".x%lx.c coords %lxBUT%d %d %d %d %d\n", + canvas, x, i, xx21, yy21, xx22, yy22); + xx11 += dx; + xx21 += dx; + xx22 += dx; + } + sys_vgui(".x%lx.c coords %lxLABEL %d %d\n", + canvas, x, xx11b + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + yy11 + x->x_gui.x_ldy * IEMGUI_ZOOM(x)); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n", + canvas, x, 0, + xx11b, yy12 + IEMGUI_ZOOM(x) - ioh, + xx11b + iow, yy12); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n", + canvas, x, 0, + xx11b, yy11, + xx11b + iow, yy11 - IEMGUI_ZOOM(x) + ioh); +} + +void hradio_draw_erase(t_hradio* x, t_glist* glist) +{ + int n = x->x_number, i; + t_canvas *canvas = glist_getcanvas(glist); + + for(i = 0; i < n; i++) + { + sys_vgui(".x%lx.c delete %lxBASE%d\n", canvas, x, i); + sys_vgui(".x%lx.c delete %lxBUT%d\n", canvas, x, i); + } + sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); +} + +void hradio_draw_config(t_hradio* x, t_glist* glist) +{ + int n = x->x_number, i; + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n", + canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight, + x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED:x->x_gui.x_lcol, + strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""); + for(i = 0; i < n; i++) + { + sys_vgui(".x%lx.c itemconfigure %lxBASE%d -fill #%06x\n", canvas, x, i, + x->x_gui.x_bcol); + sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%06x -outline #%06x\n", canvas, x, i, + (x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol, + (x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol); + } +} + +void hradio_draw_io(t_hradio* x, t_glist* glist, int old_snd_rcv_flags) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n", + canvas, + xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh, + xpos + iow, ypos + x->x_gui.x_h, + x, 0); + /* keep these above outlet */ + if(x->x_on == 0) { + sys_vgui(".x%lx.c raise %lxBUT%d %lxOUT%d\n", canvas, x, x->x_on, x, 0); + sys_vgui(".x%lx.c raise %lxLABEL %lxBUT%d\n", canvas, x, x, x->x_on); + } + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n", + canvas, + xpos, ypos, + xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh, + x, 0); + /* keep these above inlet */ + if(x->x_on == 0) { + sys_vgui(".x%lx.c raise %lxBUT%d %lxIN%d\n", canvas, x, x->x_on, x, 0); + sys_vgui(".x%lx.c raise %lxLABEL %lxBUT%d\n", canvas, x, x, x->x_on); + } + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); +} + +void hradio_draw_select(t_hradio* x, t_glist* glist) +{ + int n = x->x_number, i; + t_canvas *canvas = glist_getcanvas(glist); + + if(x->x_gui.x_fsf.x_selected) + { + for(i = 0; i < n; i++) + { + sys_vgui(".x%lx.c itemconfigure %lxBASE%d -outline #%06x\n", canvas, x, i, + IEM_GUI_COLOR_SELECTED); + } + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + } + else + { + for(i = 0; i < n; i++) + { + sys_vgui(".x%lx.c itemconfigure %lxBASE%d -outline #%06x\n", canvas, x, i, + IEM_GUI_COLOR_NORMAL); + } + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, + x->x_gui.x_lcol); + } +} + +void hradio_draw(t_hradio *x, t_glist *glist, int mode) +{ + if(mode == IEM_GUI_DRAW_MODE_UPDATE) + sys_queuegui(x, glist, hradio_draw_update); + else if(mode == IEM_GUI_DRAW_MODE_MOVE) + hradio_draw_move(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_NEW) + hradio_draw_new(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_SELECT) + hradio_draw_select(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_ERASE) + hradio_draw_erase(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_CONFIG) + hradio_draw_config(x, glist); + else if(mode >= IEM_GUI_DRAW_MODE_IO) + hradio_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO); +} + +/* ------------------------ hdl widgetbehaviour----------------------------- */ + +static void hradio_getrect(t_gobj *z, t_glist *glist, int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_hradio *x = (t_hradio *)z; + + *xp1 = text_xpix(&x->x_gui.x_obj, glist); + *yp1 = text_ypix(&x->x_gui.x_obj, glist); + *xp2 = *xp1 + x->x_gui.x_w * x->x_number; + *yp2 = *yp1 + x->x_gui.x_h; +} + +static void hradio_save(t_gobj *z, t_binbuf *b) +{ + t_hradio *x = (t_hradio *)z; + t_symbol *bflcol[3]; + t_symbol *srl[3]; + + iemgui_save(&x->x_gui, srl, bflcol); + binbuf_addv(b, "ssiisiiiisssiiiisssf", gensym("#X"),gensym("obj"), + (int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix, + (pd_class(&x->x_gui.x_obj.ob_pd) == hradio_old_class ? + gensym("hdl") : gensym("hradio")), + x->x_gui.x_w/IEMGUI_ZOOM(x), + x->x_change, iem_symargstoint(&x->x_gui.x_isa), x->x_number, + srl[0], srl[1], srl[2], + x->x_gui.x_ldx, x->x_gui.x_ldy, + iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize, + bflcol[0], bflcol[1], bflcol[2], x->x_fval); + binbuf_addv(b, ";"); +} + +static void hradio_properties(t_gobj *z, t_glist *owner) +{ + t_hradio *x = (t_hradio *)z; + char buf[800]; + t_symbol *srl[3]; + int hchange = -1; + + iemgui_properties(&x->x_gui, srl); + if(pd_class(&x->x_gui.x_obj.ob_pd) == hradio_old_class) + hchange = x->x_change; + sprintf(buf, "pdtk_iemgui_dialog %%s |hradio| \ + ----------dimensions(pix):----------- %d %d size: 0 0 empty \ + empty 0.0 empty 0.0 empty %d \ + %d new-only new&old %d %d number: %d \ + %s %s \ + %s %d %d \ + %d %d \ + #%06x #%06x #%06x\n", + x->x_gui.x_w/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE, + 0,/*no_schedule*/ + hchange, x->x_gui.x_isa.x_loadinit, -1, x->x_number, + srl[0]->s_name, srl[1]->s_name, + srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy, + x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize, + 0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol); + gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf); +} + +static void hradio_dialog(t_hradio *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *srl[3]; + int a = (int)atom_getfloatarg(0, argc, argv); + int chg = (int)atom_getfloatarg(4, argc, argv); + int num = (int)atom_getfloatarg(6, argc, argv); + int sr_flags; + + if(chg != 0) chg = 1; + x->x_change = chg; + sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv); + x->x_gui.x_w = iemgui_clip_size(a) * IEMGUI_ZOOM(x); + x->x_gui.x_h = x->x_gui.x_w; + if(x->x_number != num) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_ERASE); + x->x_number = num; + if(x->x_on >= x->x_number) + { + x->x_on = x->x_number - 1; + x->x_on_old = x->x_on; + } + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_NEW); + } + else + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x); + } + +} + +static void hradio_set(t_hradio *x, t_floatarg f) +{ + int i = (int)f; + int old = x->x_on_old; + + x->x_fval = f; + if(i < 0) + i = 0; + if(i >= x->x_number) + i = x->x_number - 1; + if(x->x_on != x->x_on_old) + { + old = x->x_on_old; + x->x_on_old = x->x_on; + x->x_on = i; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + x->x_on_old = old; + } + else + { + x->x_on = i; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + } +} + +static void hradio_bang(t_hradio *x) +{ + /* compatibility with earlier "hdial" behavior */ + if(pd_class(&x->x_gui.x_obj.ob_pd) == hradio_old_class) + { + if((x->x_change) && (x->x_on != x->x_on_old)) + { + SETFLOAT(x->x_at, (t_float)x->x_on_old); + SETFLOAT(x->x_at+1, 0.0); + outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at); + } + x->x_on_old = x->x_on; + SETFLOAT(x->x_at, (t_float)x->x_on); + SETFLOAT(x->x_at+1, 1.0); + outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at); + } + else + { + float outval = (pd_compatibilitylevel < 46 ? x->x_on : x->x_fval); + outlet_float(x->x_gui.x_obj.ob_outlet, outval); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, outval); + } +} + +static void hradio_fout(t_hradio *x, t_floatarg f) +{ + int i = (int)f; + + x->x_fval = f; + if(i < 0) + i = 0; + if(i >= x->x_number) + i = x->x_number - 1; + + if(pd_class(&x->x_gui.x_obj.ob_pd) == hradio_old_class) + { + if((x->x_change) && (i != x->x_on_old)) + { + SETFLOAT(x->x_at, (t_float)x->x_on_old); + SETFLOAT(x->x_at+1, 0.0); + outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at); + } + if(x->x_on != x->x_on_old) + x->x_on_old = x->x_on; + x->x_on = i; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + x->x_on_old = x->x_on; + SETFLOAT(x->x_at, (t_float)x->x_on); + SETFLOAT(x->x_at+1, 1.0); + outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at); + } + else + { + float outval = (pd_compatibilitylevel < 46 ? i : x->x_fval); + x->x_on_old = x->x_on; + x->x_on = i; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + outlet_float(x->x_gui.x_obj.ob_outlet, outval); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, outval); + } +} + +static void hradio_float(t_hradio *x, t_floatarg f) +{ + int i = (int)f; + x->x_fval = f; + if(i < 0) + i = 0; + if(i >= x->x_number) + i = x->x_number - 1; + + if(pd_class(&x->x_gui.x_obj.ob_pd) == hradio_old_class) + { + /* compatibility with earlier "hdial" behavior */ + if((x->x_change) && (i != x->x_on_old)) + { + if(x->x_gui.x_fsf.x_put_in2out) + { + SETFLOAT(x->x_at, (t_float)x->x_on_old); + SETFLOAT(x->x_at+1, 0.0); + outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at); + } + } + if(x->x_on != x->x_on_old) + x->x_on_old = x->x_on; + x->x_on = i; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + x->x_on_old = x->x_on; + if(x->x_gui.x_fsf.x_put_in2out) + { + SETFLOAT(x->x_at, (t_float)x->x_on); + SETFLOAT(x->x_at+1, 1.0); + outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at); + } + } + else + { + float outval = (pd_compatibilitylevel < 46 ? i : x->x_fval); + x->x_on_old = x->x_on; + x->x_on = i; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + if(x->x_gui.x_fsf.x_put_in2out) + { + outlet_float(x->x_gui.x_obj.ob_outlet, outval); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, outval); + } + } +} + +static void hradio_click(t_hradio *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + int xx = (int)xpos - (int)text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist); + + hradio_fout(x, (t_float)(xx / x->x_gui.x_w)); +} + +static int hradio_newclick(t_gobj *z, struct _glist *glist, int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + if(doit) + hradio_click((t_hradio *)z, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, 0, (t_floatarg)alt); + return (1); +} + +static void hradio_loadbang(t_hradio *x, t_floatarg action) +{ + if(action == LB_LOAD && x->x_gui.x_isa.x_loadinit) + hradio_bang(x); +} + +static void hradio_number(t_hradio *x, t_floatarg num) +{ + int n = (int)num; + + if(n < 1) + n = 1; + if(n > IEM_RADIO_MAX) + n = IEM_RADIO_MAX; + if(n != x->x_number) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_ERASE); + x->x_number = n; + if(x->x_on >= x->x_number) + x->x_on = x->x_number - 1; + x->x_on_old = x->x_on; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_NEW); + canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x); + } +} + +static void hradio_size(t_hradio *x, t_symbol *s, int ac, t_atom *av) +{ + x->x_gui.x_w = iemgui_clip_size((int)atom_getfloatarg(0, ac, av)) * IEMGUI_ZOOM(x); + x->x_gui.x_h = x->x_gui.x_w; + iemgui_size((void *)x, &x->x_gui); +} + +static void hradio_delta(t_hradio *x, t_symbol *s, int ac, t_atom *av) +{iemgui_delta((void *)x, &x->x_gui, s, ac, av);} + +static void hradio_pos(t_hradio *x, t_symbol *s, int ac, t_atom *av) +{iemgui_pos((void *)x, &x->x_gui, s, ac, av);} + +static void hradio_color(t_hradio *x, t_symbol *s, int ac, t_atom *av) +{iemgui_color((void *)x, &x->x_gui, s, ac, av);} + +static void hradio_send(t_hradio *x, t_symbol *s) +{iemgui_send(x, &x->x_gui, s);} + +static void hradio_receive(t_hradio *x, t_symbol *s) +{iemgui_receive(x, &x->x_gui, s);} + +static void hradio_label(t_hradio *x, t_symbol *s) +{iemgui_label((void *)x, &x->x_gui, s);} + +static void hradio_label_pos(t_hradio *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);} + +static void hradio_label_font(t_hradio *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);} + +static void hradio_init(t_hradio *x, t_floatarg f) +{x->x_gui.x_isa.x_loadinit = (f == 0.0) ? 0 : 1;} + +static void hradio_double_change(t_hradio *x) +{x->x_change = 1;} + +static void hradio_single_change(t_hradio *x) +{x->x_change = 0;} + +static void *hradio_donew(t_symbol *s, int argc, t_atom *argv, int old) +{ + t_hradio *x = (t_hradio *)pd_new(old ? hradio_old_class : hradio_class); + int a=IEM_GUI_DEFAULTSIZE, on = 0, f = 0; + int ldx = 0, ldy = -8, chg = 1, num = 8; + int fs = 10; + int ftbreak = IEM_BNG_DEFAULTBREAKFLASHTIME, fthold = IEM_BNG_DEFAULTHOLDFLASHTIME; + char str[144]; + float fval = 0; + + iem_inttosymargs(&x->x_gui.x_isa, 0); + iem_inttofstyle(&x->x_gui.x_fsf, 0); + + x->x_gui.x_bcol = 0xFCFCFC; + x->x_gui.x_fcol = 0x00; + x->x_gui.x_lcol = 0x00; + + if((argc == 15)&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)&&IS_A_FLOAT(argv,2) + &&IS_A_FLOAT(argv,3) + &&(IS_A_SYMBOL(argv,4)||IS_A_FLOAT(argv,4)) + &&(IS_A_SYMBOL(argv,5)||IS_A_FLOAT(argv,5)) + &&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6)) + &&IS_A_FLOAT(argv,7)&&IS_A_FLOAT(argv,8) + &&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10)&&IS_A_FLOAT(argv,14)) + { + a = (int)atom_getfloatarg(0, argc, argv); + chg = (int)atom_getfloatarg(1, argc, argv); + iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(2, argc, argv)); + num = (int)atom_getfloatarg(3, argc, argv); + iemgui_new_getnames(&x->x_gui, 4, argv); + ldx = (int)atom_getfloatarg(7, argc, argv); + ldy = (int)atom_getfloatarg(8, argc, argv); + iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(9, argc, argv)); + fs = (int)atom_getfloatarg(10, argc, argv); + iemgui_all_loadcolors(&x->x_gui, argv+11, argv+12, argv+13); + fval = atom_getfloatarg(14, argc, argv); + } + else iemgui_new_getnames(&x->x_gui, 4, 0); + x->x_gui.x_draw = (t_iemfunptr)hradio_draw; + x->x_gui.x_fsf.x_snd_able = 1; + x->x_gui.x_fsf.x_rcv_able = 1; + x->x_gui.x_glist = (t_glist *)canvas_getcurrent(); + if(!strcmp(x->x_gui.x_snd->s_name, "empty")) + x->x_gui.x_fsf.x_snd_able = 0; + if(!strcmp(x->x_gui.x_rcv->s_name, "empty")) + x->x_gui.x_fsf.x_rcv_able = 0; + if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica"); + else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times"); + else { x->x_gui.x_fsf.x_font_style = 0; + strcpy(x->x_gui.x_font, sys_font); } + if(num < 1) + num = 1; + if(num > IEM_RADIO_MAX) + num = IEM_RADIO_MAX; + x->x_number = num; + x->x_fval = fval; + on = fval; + if(on < 0) + on = 0; + if(on >= x->x_number) + on = x->x_number - 1; + if(x->x_gui.x_isa.x_loadinit) + x->x_on = on; + else + x->x_on = 0; + x->x_on_old = x->x_on; + x->x_change = (chg == 0) ? 0 : 1; + if(x->x_gui.x_fsf.x_rcv_able) + pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + x->x_gui.x_ldx = ldx; + x->x_gui.x_ldy = ldy; + if(fs < 4) + fs = 4; + x->x_gui.x_fontsize = fs; + x->x_gui.x_w = iemgui_clip_size(a); + x->x_gui.x_h = x->x_gui.x_w; + iemgui_verify_snd_ne_rcv(&x->x_gui); + iemgui_newzoom(&x->x_gui); + outlet_new(&x->x_gui.x_obj, &s_list); + return (x); +} + +static void *hradio_new(t_symbol *s, int argc, t_atom *argv) +{ + return (hradio_donew(s, argc, argv, 0)); +} + +static void *hdial_new(t_symbol *s, int argc, t_atom *argv) +{ + return (hradio_donew(s, argc, argv, 1)); +} + +static void hradio_ff(t_hradio *x) +{ + if(x->x_gui.x_fsf.x_rcv_able) + pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + gfxstub_deleteforkey(x); +} + +void g_hradio_setup(void) +{ + hradio_class = class_new(gensym("hradio"), (t_newmethod)hradio_new, + (t_method)hradio_ff, sizeof(t_hradio), 0, A_GIMME, 0); + class_addbang(hradio_class, hradio_bang); + class_addfloat(hradio_class, hradio_float); + class_addmethod(hradio_class, (t_method)hradio_click, + gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(hradio_class, (t_method)hradio_dialog, + gensym("dialog"), A_GIMME, 0); + class_addmethod(hradio_class, (t_method)hradio_loadbang, + gensym("loadbang"), A_DEFFLOAT, 0); + class_addmethod(hradio_class, (t_method)hradio_set, + gensym("set"), A_FLOAT, 0); + class_addmethod(hradio_class, (t_method)hradio_size, + gensym("size"), A_GIMME, 0); + class_addmethod(hradio_class, (t_method)hradio_delta, + gensym("delta"), A_GIMME, 0); + class_addmethod(hradio_class, (t_method)hradio_pos, + gensym("pos"), A_GIMME, 0); + class_addmethod(hradio_class, (t_method)hradio_color, + gensym("color"), A_GIMME, 0); + class_addmethod(hradio_class, (t_method)hradio_send, + gensym("send"), A_DEFSYM, 0); + class_addmethod(hradio_class, (t_method)hradio_receive, + gensym("receive"), A_DEFSYM, 0); + class_addmethod(hradio_class, (t_method)hradio_label, + gensym("label"), A_DEFSYM, 0); + class_addmethod(hradio_class, (t_method)hradio_label_pos, + gensym("label_pos"), A_GIMME, 0); + class_addmethod(hradio_class, (t_method)hradio_label_font, + gensym("label_font"), A_GIMME, 0); + class_addmethod(hradio_class, (t_method)hradio_init, + gensym("init"), A_FLOAT, 0); + class_addmethod(hradio_class, (t_method)hradio_number, + gensym("number"), A_FLOAT, 0); + class_addmethod(hradio_class, (t_method)hradio_single_change, + gensym("single_change"), 0); + class_addmethod(hradio_class, (t_method)hradio_double_change, + gensym("double_change"), 0); + class_addmethod(hradio_class, (t_method)iemgui_zoom, + gensym("zoom"), A_CANT, 0); + hradio_widgetbehavior.w_getrectfn = hradio_getrect; + hradio_widgetbehavior.w_displacefn = iemgui_displace; + hradio_widgetbehavior.w_selectfn = iemgui_select; + hradio_widgetbehavior.w_activatefn = NULL; + hradio_widgetbehavior.w_deletefn = iemgui_delete; + hradio_widgetbehavior.w_visfn = iemgui_vis; + hradio_widgetbehavior.w_clickfn = hradio_newclick; + class_setwidget(hradio_class, &hradio_widgetbehavior); + class_sethelpsymbol(hradio_class, gensym("hradio")); + class_setsavefn(hradio_class, hradio_save); + class_setpropertiesfn(hradio_class, hradio_properties); + + /*obsolete version (0.34-0.35) */ + hradio_old_class = class_new(gensym("hdl"), (t_newmethod)hdial_new, + (t_method)hradio_ff, sizeof(t_hradio), 0, A_GIMME, 0); + class_addcreator((t_newmethod)hradio_new, gensym("rdb"), A_GIMME, 0); + class_addcreator((t_newmethod)hradio_new, gensym("radiobut"), A_GIMME, 0); + class_addcreator((t_newmethod)hradio_new, gensym("radiobutton"), + A_GIMME, 0); + class_addbang(hradio_old_class, hradio_bang); + class_addfloat(hradio_old_class, hradio_float); + class_addmethod(hradio_old_class, (t_method)hradio_click, + gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(hradio_old_class, (t_method)hradio_dialog, + gensym("dialog"), A_GIMME, 0); + class_addmethod(hradio_old_class, (t_method)hradio_loadbang, + gensym("loadbang"), 0); + class_addmethod(hradio_old_class, (t_method)hradio_set, + gensym("set"), A_FLOAT, 0); + class_addmethod(hradio_old_class, (t_method)hradio_size, + gensym("size"), A_GIMME, 0); + class_addmethod(hradio_old_class, (t_method)hradio_delta, + gensym("delta"), A_GIMME, 0); + class_addmethod(hradio_old_class, (t_method)hradio_pos, + gensym("pos"), A_GIMME, 0); + class_addmethod(hradio_old_class, (t_method)hradio_color, + gensym("color"), A_GIMME, 0); + class_addmethod(hradio_old_class, (t_method)hradio_send, + gensym("send"), A_DEFSYM, 0); + class_addmethod(hradio_old_class, (t_method)hradio_receive, + gensym("receive"), A_DEFSYM, 0); + class_addmethod(hradio_old_class, (t_method)hradio_label, + gensym("label"), A_DEFSYM, 0); + class_addmethod(hradio_old_class, (t_method)hradio_label_pos, + gensym("label_pos"), A_GIMME, 0); + class_addmethod(hradio_old_class, (t_method)hradio_label_font, + gensym("label_font"), A_GIMME, 0); + class_addmethod(hradio_old_class, (t_method)hradio_init, + gensym("init"), A_FLOAT, 0); + class_addmethod(hradio_old_class, (t_method)hradio_number, + gensym("number"), A_FLOAT, 0); + class_addmethod(hradio_old_class, (t_method)hradio_single_change, + gensym("single_change"), 0); + class_addmethod(hradio_old_class, (t_method)hradio_double_change, + gensym("double_change"), 0); + class_addmethod(hradio_old_class, (t_method)iemgui_zoom, + gensym("zoom"), A_CANT, 0); + class_setwidget(hradio_old_class, &hradio_widgetbehavior); + class_sethelpsymbol(hradio_old_class, gensym("hradio")); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_hslider.c b/ports/camomile/source/LibPd/pure-data/src/g_hslider.c new file mode 100644 index 00000000..167d6e0b --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_hslider.c @@ -0,0 +1,691 @@ +/* Copyright (c) 1997-1999 Miller Puckette. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */ +/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */ + +#include +#include +#include +#include +#include "m_pd.h" +#include "g_canvas.h" + +#include "g_all_guis.h" +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +#define LMARGIN 3 +#define RMARGIN 2 + +/* ------------ hsl gui-horizontal slider ----------------------- */ + +t_widgetbehavior hslider_widgetbehavior; +static t_class *hslider_class; + +/* widget helper functions */ + +static void hslider_draw_update(t_gobj *client, t_glist *glist) +{ + t_hslider *x = (t_hslider *)client; + if (glist_isvisible(glist)) + { + int r = text_xpix(&x->x_gui.x_obj, glist) + ((x->x_val + 50)/100); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + t_canvas *canvas = glist_getcanvas(glist); + sys_vgui(".x%lx.c coords %lxKNOB %d %d %d %d\n", + canvas, x, r, ypos + IEMGUI_ZOOM(x), + r, ypos + x->x_gui.x_h - IEMGUI_ZOOM(x)); + } +} + +static void hslider_draw_new(t_hslider *x, t_glist *glist) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + int lmargin = LMARGIN * IEMGUI_ZOOM(x), rmargin = RMARGIN * IEMGUI_ZOOM(x); + int r = xpos + (x->x_val + 50)/100; + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -fill #%06x -tags %lxBASE\n", + canvas, xpos - lmargin, ypos, + xpos + x->x_gui.x_w + rmargin, ypos + x->x_gui.x_h, + IEMGUI_ZOOM(x), + x->x_gui.x_bcol, x); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n", + canvas, + xpos - lmargin, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh, + xpos - lmargin + iow, ypos + x->x_gui.x_h, + x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n", + canvas, + xpos - lmargin, ypos, + xpos - lmargin + iow, ypos - IEMGUI_ZOOM(x) + ioh, + x, 0); + sys_vgui(".x%lx.c create line %d %d %d %d -width %d -fill #%06x -tags %lxKNOB\n", + canvas, r, ypos + IEMGUI_ZOOM(x), + r, ypos + x->x_gui.x_h - IEMGUI_ZOOM(x), + 1 + 2 * IEMGUI_ZOOM(x), x->x_gui.x_fcol, x); + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \ + -font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n", + canvas, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x), + (strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""), + x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + x->x_gui.x_lcol, x); +} + +static void hslider_draw_move(t_hslider *x, t_glist *glist) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + int lmargin = LMARGIN * IEMGUI_ZOOM(x), rmargin = RMARGIN * IEMGUI_ZOOM(x); + int r = xpos + (x->x_val + 50)/100; + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n", + canvas, x, + xpos - lmargin, ypos, + xpos + x->x_gui.x_w + rmargin, ypos + x->x_gui.x_h); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n", + canvas, x, 0, + xpos - lmargin, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh, + xpos - lmargin + iow, ypos + x->x_gui.x_h); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n", + canvas, x, 0, + xpos - lmargin, ypos, + xpos - lmargin + iow, ypos - IEMGUI_ZOOM(x) + ioh); + sys_vgui(".x%lx.c coords %lxKNOB %d %d %d %d\n", + canvas, x, r, ypos + IEMGUI_ZOOM(x), + r, ypos + x->x_gui.x_h - IEMGUI_ZOOM(x)); + sys_vgui(".x%lx.c coords %lxLABEL %d %d\n", + canvas, x, xpos+x->x_gui.x_ldx * IEMGUI_ZOOM(x), + ypos+x->x_gui.x_ldy * IEMGUI_ZOOM(x)); +} + +static void hslider_draw_erase(t_hslider* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c delete %lxBASE\n", canvas, x); + sys_vgui(".x%lx.c delete %lxKNOB\n", canvas, x); + sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); +} + +static void hslider_draw_config(t_hslider* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n", + canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + (x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol), + (strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : "")); + sys_vgui(".x%lx.c itemconfigure %lxKNOB -fill #%06x\n", canvas, x, x->x_gui.x_fcol); + sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%06x\n", canvas, x, x->x_gui.x_bcol); +} + +static void hslider_draw_io(t_hslider* x, t_glist* glist, int old_snd_rcv_flags) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + int lmargin = LMARGIN * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n", + canvas, + xpos - lmargin, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh, + xpos - lmargin + iow, ypos + x->x_gui.x_h, + x, 0); + /* keep these above outlet */ + sys_vgui(".x%lx.c raise %lxKNOB %lxOUT%d\n", canvas, x, x, 0); + sys_vgui(".x%lx.c raise %lxLABEL %lxKNOB\n", canvas, x, x); + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n", + canvas, + xpos - lmargin, ypos, + xpos - lmargin + iow, ypos - IEMGUI_ZOOM(x) + ioh, + x, 0); + /* keep these above inlet */ + sys_vgui(".x%lx.c raise %lxKNOB %lxIN%d\n", canvas, x, x, 0); + sys_vgui(".x%lx.c raise %lxLABEL %lxKNOB\n", canvas, x, x); + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); +} + +static void hslider_draw_select(t_hslider* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + if(x->x_gui.x_fsf.x_selected) + { + sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + } + else + { + sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_NORMAL); + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, x->x_gui.x_lcol); + } +} + +void hslider_draw(t_hslider *x, t_glist *glist, int mode) +{ + if(mode == IEM_GUI_DRAW_MODE_UPDATE) + sys_queuegui(x, glist, hslider_draw_update); + else if(mode == IEM_GUI_DRAW_MODE_MOVE) + hslider_draw_move(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_NEW) + hslider_draw_new(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_SELECT) + hslider_draw_select(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_ERASE) + hslider_draw_erase(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_CONFIG) + hslider_draw_config(x, glist); + else if(mode >= IEM_GUI_DRAW_MODE_IO) + hslider_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO); +} + +/* ------------------------ hsl widgetbehaviour----------------------------- */ + + +static void hslider_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_hslider* x = (t_hslider*)z; + + *xp1 = text_xpix(&x->x_gui.x_obj, glist) - LMARGIN*glist_getzoom(glist); + *yp1 = text_ypix(&x->x_gui.x_obj, glist); + *xp2 = *xp1 + x->x_gui.x_w + (LMARGIN + RMARGIN)*glist_getzoom(glist); + *yp2 = *yp1 + x->x_gui.x_h; +} + +static void hslider_save(t_gobj *z, t_binbuf *b) +{ + t_hslider *x = (t_hslider *)z; + t_symbol *bflcol[3]; + t_symbol *srl[3]; + + iemgui_save(&x->x_gui, srl, bflcol); + binbuf_addv(b, "ssiisiiffiisssiiiisssii", gensym("#X"), gensym("obj"), + (int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix, + gensym("hsl"), x->x_gui.x_w/IEMGUI_ZOOM(x), x->x_gui.x_h/IEMGUI_ZOOM(x), + (t_float)x->x_min, (t_float)x->x_max, + x->x_lin0_log1, iem_symargstoint(&x->x_gui.x_isa), + srl[0], srl[1], srl[2], + x->x_gui.x_ldx, x->x_gui.x_ldy, + iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize, + bflcol[0], bflcol[1], bflcol[2], + x->x_val, x->x_steady); + binbuf_addv(b, ";"); +} + +void hslider_check_width(t_hslider *x, int w) +{ + if(w < IEM_SL_MINSIZE * IEMGUI_ZOOM(x)) + w = IEM_SL_MINSIZE * IEMGUI_ZOOM(x); + x->x_gui.x_w = w; + if(x->x_val > (x->x_gui.x_w*100 - 100)) + { + x->x_pos = x->x_gui.x_w*100 - 100; + x->x_val = x->x_pos; + } + if(x->x_lin0_log1) + x->x_k = log(x->x_max/x->x_min) / (double)(x->x_gui.x_w/IEMGUI_ZOOM(x) - 1); + else + x->x_k = (x->x_max - x->x_min) / (double)(x->x_gui.x_w/IEMGUI_ZOOM(x) - 1); +} + +void hslider_check_minmax(t_hslider *x, double min, double max) +{ + if(x->x_lin0_log1) + { + if((min == 0.0) && (max == 0.0)) + max = 1.0; + if(max > 0.0) + { + if(min <= 0.0) + min = 0.01*max; + } + else + { + if(min > 0.0) + max = 0.01*min; + } + } + x->x_min = min; + x->x_max = max; + if(x->x_lin0_log1) + x->x_k = log(x->x_max/x->x_min) / (double)(x->x_gui.x_w/IEMGUI_ZOOM(x) - 1); + else + x->x_k = (x->x_max - x->x_min) / (double)(x->x_gui.x_w/IEMGUI_ZOOM(x) - 1); +} + +static void hslider_properties(t_gobj *z, t_glist *owner) +{ + t_hslider *x = (t_hslider *)z; + char buf[800]; + t_symbol *srl[3]; + + iemgui_properties(&x->x_gui, srl); + sprintf(buf, "pdtk_iemgui_dialog %%s |hsl| \ + --------dimensions(pix)(pix):-------- %d %d width: %d %d height: \ + -----------output-range:----------- %g left: %g right: %g \ + %d lin log %d %d empty %d \ + %s %s \ + %s %d %d \ + %d %d \ + #%06x #%06x #%06x\n", + x->x_gui.x_w/IEMGUI_ZOOM(x), IEM_SL_MINSIZE, x->x_gui.x_h/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE, + x->x_min, x->x_max, 0.0,/*no_schedule*/ + x->x_lin0_log1, x->x_gui.x_isa.x_loadinit, x->x_steady, -1,/*no multi, but iem-characteristic*/ + srl[0]->s_name, srl[1]->s_name, + srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy, + x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize, + 0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol); + gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf); +} + +static void hslider_set(t_hslider *x, t_floatarg f) /* bugfix */ +{ + int old = x->x_val; + double g; + + x->x_fval = f; + if (x->x_min > x->x_max) + { + if(f > x->x_min) + f = x->x_min; + if(f < x->x_max) + f = x->x_max; + } + else + { + if(f > x->x_max) + f = x->x_max; + if(f < x->x_min) + f = x->x_min; + } + if(x->x_lin0_log1) + g = log(f/x->x_min) / x->x_k; + else + g = (f - x->x_min) / x->x_k; + x->x_val = IEMGUI_ZOOM(x) * (int)(100.0*g + 0.49999); + x->x_pos = x->x_val; + if(x->x_val != old) + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); +} + + /* compute numeric value (fval) from pixel location (val) and range */ +static t_float hslider_getfval(t_hslider *x) +{ + t_float fval; + int zoomval = (x->x_gui.x_fsf.x_finemoved) ? + x->x_val/IEMGUI_ZOOM(x) : (x->x_val / (100*IEMGUI_ZOOM(x))) * 100; + + if (x->x_lin0_log1) + fval = x->x_min * exp(x->x_k * (double)(zoomval) * 0.01); + else fval = (double)(zoomval) * 0.01 * x->x_k + x->x_min; + if ((fval < 1.0e-10) && (fval > -1.0e-10)) + fval = 0.0; + return (fval); +} + +static void hslider_bang(t_hslider *x) +{ + double out; + + if (pd_compatibilitylevel < 46) + out = hslider_getfval(x); + else out = x->x_fval; + outlet_float(x->x_gui.x_obj.ob_outlet, out); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, out); +} + +static void hslider_dialog(t_hslider *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *srl[3]; + int w = (int)atom_getfloatarg(0, argc, argv) * IEMGUI_ZOOM(x); + int h = (int)atom_getfloatarg(1, argc, argv); + double min = (double)atom_getfloatarg(2, argc, argv); + double max = (double)atom_getfloatarg(3, argc, argv); + int lilo = (int)atom_getfloatarg(4, argc, argv); + int steady = (int)atom_getfloatarg(17, argc, argv); + int sr_flags; + + if(lilo != 0) lilo = 1; + x->x_lin0_log1 = lilo; + if(steady) + x->x_steady = 1; + else + x->x_steady = 0; + sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv); + x->x_gui.x_h = iemgui_clip_size(h) * IEMGUI_ZOOM(x); + hslider_check_width(x, w); + hslider_check_minmax(x, min, max); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x); +} + +static void hslider_motion(t_hslider *x, t_floatarg dx, t_floatarg dy) +{ + int old = x->x_val; + + if(x->x_gui.x_fsf.x_finemoved) + x->x_pos += (int)dx; + else + x->x_pos += 100 * (int)dx; + x->x_val = x->x_pos; + if(x->x_val > (100*x->x_gui.x_w - 100)) + { + x->x_val = 100*x->x_gui.x_w - 100; + x->x_pos += 50; + x->x_pos -= x->x_pos % 100; + } + if(x->x_val < 0) + { + x->x_val = 0; + x->x_pos -= 50; + x->x_pos -= x->x_pos % 100; + } + x->x_fval = hslider_getfval(x); + if (old != x->x_val) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + hslider_bang(x); + } +} + +static void hslider_click(t_hslider *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + if(!x->x_steady) + x->x_val = (int)(100.0 * (xpos - text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist))); + if(x->x_val > (100*x->x_gui.x_w - 100)) + x->x_val = 100*x->x_gui.x_w - 100; + if(x->x_val < 0) + x->x_val = 0; + x->x_fval = hslider_getfval(x); + x->x_pos = x->x_val; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + hslider_bang(x); + glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, (t_glistmotionfn)hslider_motion, + 0, xpos, ypos); +} + +static int hslider_newclick(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_hslider* x = (t_hslider *)z; + + if(doit) + { + hslider_click(x, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, + 0, (t_floatarg)alt); + if(shift) + x->x_gui.x_fsf.x_finemoved = 1; + else + x->x_gui.x_fsf.x_finemoved = 0; + } + return (1); +} + +static void hslider_size(t_hslider *x, t_symbol *s, int ac, t_atom *av) +{ + hslider_check_width(x, (int)atom_getfloatarg(0, ac, av)*IEMGUI_ZOOM(x)); + if(ac > 1) + x->x_gui.x_h = iemgui_clip_size((int)atom_getfloatarg(1, ac, av))*IEMGUI_ZOOM(x); + iemgui_size((void *)x, &x->x_gui); +} + +static void hslider_delta(t_hslider *x, t_symbol *s, int ac, t_atom *av) +{iemgui_delta((void *)x, &x->x_gui, s, ac, av);} + +static void hslider_pos(t_hslider *x, t_symbol *s, int ac, t_atom *av) +{iemgui_pos((void *)x, &x->x_gui, s, ac, av);} + +static void hslider_range(t_hslider *x, t_symbol *s, int ac, t_atom *av) +{ + hslider_check_minmax(x, (double)atom_getfloatarg(0, ac, av), + (double)atom_getfloatarg(1, ac, av)); +} + +static void hslider_color(t_hslider *x, t_symbol *s, int ac, t_atom *av) +{iemgui_color((void *)x, &x->x_gui, s, ac, av);} + +static void hslider_send(t_hslider *x, t_symbol *s) +{iemgui_send(x, &x->x_gui, s);} + +static void hslider_receive(t_hslider *x, t_symbol *s) +{iemgui_receive(x, &x->x_gui, s);} + +static void hslider_label(t_hslider *x, t_symbol *s) +{iemgui_label((void *)x, &x->x_gui, s);} + +static void hslider_label_pos(t_hslider *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);} + +static void hslider_label_font(t_hslider *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);} + +static void hslider_log(t_hslider *x) +{ + x->x_lin0_log1 = 1; + hslider_check_minmax(x, x->x_min, x->x_max); +} + +static void hslider_lin(t_hslider *x) +{ + x->x_lin0_log1 = 0; + x->x_k = (x->x_max - x->x_min) / (double)(x->x_gui.x_w/IEMGUI_ZOOM(x) - 1); +} + +static void hslider_init(t_hslider *x, t_floatarg f) +{ + x->x_gui.x_isa.x_loadinit = (f == 0.0) ? 0 : 1; +} + +static void hslider_steady(t_hslider *x, t_floatarg f) +{ + x->x_steady = (f == 0.0) ? 0 : 1; +} + +static void hslider_zoom(t_hslider *x, t_floatarg f) +{ + /* scale current pixel value */ + x->x_val = (IEMGUI_ZOOM(x) == 2 ? (x->x_val)/2 : (x->x_val)*2); + x->x_pos = x->x_val; + iemgui_zoom(&x->x_gui, f); +} + +static void hslider_float(t_hslider *x, t_floatarg f) +{ + hslider_set(x, f); + if(x->x_gui.x_fsf.x_put_in2out) + hslider_bang(x); +} + +static void hslider_loadbang(t_hslider *x, t_floatarg action) +{ + if (action == LB_LOAD && x->x_gui.x_isa.x_loadinit) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + hslider_bang(x); + } +} + +static void *hslider_new(t_symbol *s, int argc, t_atom *argv) +{ + t_hslider *x = (t_hslider *)pd_new(hslider_class); + int w = IEM_SL_DEFAULTSIZE, h = IEM_GUI_DEFAULTSIZE; + int lilo = 0, ldx = -2, ldy = -8, f = 0, steady = 1; + int fs = 10; + double min = 0.0, max = (double)(IEM_SL_DEFAULTSIZE-1); + char str[144]; + float v = 0; + + iem_inttosymargs(&x->x_gui.x_isa, 0); + iem_inttofstyle(&x->x_gui.x_fsf, 0); + + x->x_gui.x_bcol = 0xFCFCFC; + x->x_gui.x_fcol = 0x00; + x->x_gui.x_lcol = 0x00; + + if(((argc == 17)||(argc == 18))&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1) + &&IS_A_FLOAT(argv,2)&&IS_A_FLOAT(argv,3) + &&IS_A_FLOAT(argv,4)&&IS_A_FLOAT(argv,5) + &&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6)) + &&(IS_A_SYMBOL(argv,7)||IS_A_FLOAT(argv,7)) + &&(IS_A_SYMBOL(argv,8)||IS_A_FLOAT(argv,8)) + &&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10) + &&IS_A_FLOAT(argv,11)&&IS_A_FLOAT(argv,12)&&IS_A_FLOAT(argv,16)) + { + w = (int)atom_getfloatarg(0, argc, argv); + h = (int)atom_getfloatarg(1, argc, argv); + min = (double)atom_getfloatarg(2, argc, argv); + max = (double)atom_getfloatarg(3, argc, argv); + lilo = (int)atom_getfloatarg(4, argc, argv); + iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(5, argc, argv)); + iemgui_new_getnames(&x->x_gui, 6, argv); + ldx = (int)atom_getfloatarg(9, argc, argv); + ldy = (int)atom_getfloatarg(10, argc, argv); + iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(11, argc, argv)); + fs = (int)atom_getfloatarg(12, argc, argv); + iemgui_all_loadcolors(&x->x_gui, argv+13, argv+14, argv+15); + v = atom_getfloatarg(16, argc, argv); + } + else iemgui_new_getnames(&x->x_gui, 6, 0); + if((argc == 18)&&IS_A_FLOAT(argv,17)) + steady = (int)atom_getfloatarg(17, argc, argv); + x->x_gui.x_draw = (t_iemfunptr)hslider_draw; + x->x_gui.x_fsf.x_snd_able = 1; + x->x_gui.x_fsf.x_rcv_able = 1; + x->x_gui.x_glist = (t_glist *)canvas_getcurrent(); + if (x->x_gui.x_isa.x_loadinit) + x->x_val = v; + else x->x_val = 0; + x->x_pos = x->x_val; + if(lilo != 0) lilo = 1; + x->x_lin0_log1 = lilo; + if(steady != 0) steady = 1; + x->x_steady = steady; + if (!strcmp(x->x_gui.x_snd->s_name, "empty")) + x->x_gui.x_fsf.x_snd_able = 0; + if (!strcmp(x->x_gui.x_rcv->s_name, "empty")) + x->x_gui.x_fsf.x_rcv_able = 0; + if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica"); + else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times"); + else { x->x_gui.x_fsf.x_font_style = 0; + strcpy(x->x_gui.x_font, sys_font); } + if (x->x_gui.x_fsf.x_rcv_able) + pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + x->x_gui.x_ldx = ldx; + x->x_gui.x_ldy = ldy; + if(fs < 4) + fs = 4; + x->x_gui.x_fontsize = fs; + x->x_gui.x_h = iemgui_clip_size(h); + hslider_check_width(x, w); + iemgui_verify_snd_ne_rcv(&x->x_gui); + iemgui_newzoom(&x->x_gui); + hslider_check_minmax(x, min, max); + outlet_new(&x->x_gui.x_obj, &s_float); + x->x_fval = hslider_getfval(x); + return (x); +} + +static void hslider_free(t_hslider *x) +{ + if(x->x_gui.x_fsf.x_rcv_able) + pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + gfxstub_deleteforkey(x); +} + +void g_hslider_setup(void) +{ + hslider_class = class_new(gensym("hsl"), (t_newmethod)hslider_new, + (t_method)hslider_free, sizeof(t_hslider), 0, A_GIMME, 0); +#ifndef GGEE_HSLIDER_COMPATIBLE + class_addcreator((t_newmethod)hslider_new, gensym("hslider"), A_GIMME, 0); +#endif + class_addbang(hslider_class, hslider_bang); + class_addfloat(hslider_class, hslider_float); + class_addmethod(hslider_class, (t_method)hslider_click, + gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(hslider_class, (t_method)hslider_motion, + gensym("motion"), A_FLOAT, A_FLOAT, 0); + class_addmethod(hslider_class, (t_method)hslider_dialog, + gensym("dialog"), A_GIMME, 0); + class_addmethod(hslider_class, (t_method)hslider_loadbang, + gensym("loadbang"), A_DEFFLOAT, 0); + class_addmethod(hslider_class, (t_method)hslider_set, + gensym("set"), A_FLOAT, 0); + class_addmethod(hslider_class, (t_method)hslider_size, + gensym("size"), A_GIMME, 0); + class_addmethod(hslider_class, (t_method)hslider_delta, + gensym("delta"), A_GIMME, 0); + class_addmethod(hslider_class, (t_method)hslider_pos, + gensym("pos"), A_GIMME, 0); + class_addmethod(hslider_class, (t_method)hslider_range, + gensym("range"), A_GIMME, 0); + class_addmethod(hslider_class, (t_method)hslider_color, + gensym("color"), A_GIMME, 0); + class_addmethod(hslider_class, (t_method)hslider_send, + gensym("send"), A_DEFSYM, 0); + class_addmethod(hslider_class, (t_method)hslider_receive, + gensym("receive"), A_DEFSYM, 0); + class_addmethod(hslider_class, (t_method)hslider_label, + gensym("label"), A_DEFSYM, 0); + class_addmethod(hslider_class, (t_method)hslider_label_pos, + gensym("label_pos"), A_GIMME, 0); + class_addmethod(hslider_class, (t_method)hslider_label_font, + gensym("label_font"), A_GIMME, 0); + class_addmethod(hslider_class, (t_method)hslider_log, + gensym("log"), 0); + class_addmethod(hslider_class, (t_method)hslider_lin, + gensym("lin"), 0); + class_addmethod(hslider_class, (t_method)hslider_init, + gensym("init"), A_FLOAT, 0); + class_addmethod(hslider_class, (t_method)hslider_steady, + gensym("steady"), A_FLOAT, 0); + class_addmethod(hslider_class, (t_method)hslider_zoom, + gensym("zoom"), A_CANT, 0); + hslider_widgetbehavior.w_getrectfn = hslider_getrect; + hslider_widgetbehavior.w_displacefn = iemgui_displace; + hslider_widgetbehavior.w_selectfn = iemgui_select; + hslider_widgetbehavior.w_activatefn = NULL; + hslider_widgetbehavior.w_deletefn = iemgui_delete; + hslider_widgetbehavior.w_visfn = iemgui_vis; + hslider_widgetbehavior.w_clickfn = hslider_newclick; + class_setwidget(hslider_class, &hslider_widgetbehavior); + class_sethelpsymbol(hslider_class, gensym("hslider")); + class_setsavefn(hslider_class, hslider_save); + class_setpropertiesfn(hslider_class, hslider_properties); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_io.c b/ports/camomile/source/LibPd/pure-data/src/g_io.c new file mode 100644 index 00000000..e842deeb --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_io.c @@ -0,0 +1,599 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* graphical inlets and outlets, both for control and signals. */ + +/* This code is highly inefficient; messages actually have to be forwarded +by inlets and outlets. The outlet is in even worse shape than the inlet; +in order to avoid having a "signal" method in the class, the oulet actually +sprouts an inlet, which forwards the message to the "outlet" object, which +sends it on to the outlet proper. Another way to do it would be to have +separate classes for "signal" and "control" outlets, but this would complicate +life elsewhere. */ + + +#include "m_pd.h" +#include "g_canvas.h" +#include +void signal_setborrowed(t_signal *sig, t_signal *sig2); +void signal_makereusable(t_signal *sig); + +/* ------------------------- vinlet -------------------------- */ +t_class *vinlet_class; + +typedef struct _vinlet +{ + t_object x_obj; + t_canvas *x_canvas; + t_inlet *x_inlet; + int x_bufsize; + t_float *x_buf; /* signal buffer; zero if not a signal */ + t_float *x_endbuf; + t_float *x_fill; + t_float *x_read; + int x_hop; + /* if not reblocking, the next slot communicates the parent's inlet + signal from the prolog to the DSP routine: */ + t_signal *x_directsignal; + + t_resample x_updown; +} t_vinlet; + +static void *vinlet_new(t_symbol *s) +{ + t_vinlet *x = (t_vinlet *)pd_new(vinlet_class); + x->x_canvas = canvas_getcurrent(); + x->x_inlet = canvas_addinlet(x->x_canvas, &x->x_obj.ob_pd, 0); + x->x_bufsize = 0; + x->x_buf = 0; + outlet_new(&x->x_obj, 0); + return (x); +} + +static void vinlet_bang(t_vinlet *x) +{ + outlet_bang(x->x_obj.ob_outlet); +} + +static void vinlet_pointer(t_vinlet *x, t_gpointer *gp) +{ + outlet_pointer(x->x_obj.ob_outlet, gp); +} + +static void vinlet_float(t_vinlet *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, f); +} + +static void vinlet_symbol(t_vinlet *x, t_symbol *s) +{ + outlet_symbol(x->x_obj.ob_outlet, s); +} + +static void vinlet_list(t_vinlet *x, t_symbol *s, int argc, t_atom *argv) +{ + outlet_list(x->x_obj.ob_outlet, s, argc, argv); +} + +static void vinlet_anything(t_vinlet *x, t_symbol *s, int argc, t_atom *argv) +{ + outlet_anything(x->x_obj.ob_outlet, s, argc, argv); +} + +static void vinlet_free(t_vinlet *x) +{ + canvas_rminlet(x->x_canvas, x->x_inlet); + if (x->x_buf) + t_freebytes(x->x_buf, x->x_bufsize * sizeof(*x->x_buf)); + resample_free(&x->x_updown); +} + +t_inlet *vinlet_getit(t_pd *x) +{ + if (pd_class(x) != vinlet_class) bug("vinlet_getit"); + return (((t_vinlet *)x)->x_inlet); +} + +/* ------------------------- signal inlet -------------------------- */ +int vinlet_issignal(t_vinlet *x) +{ + return (x->x_buf != 0); +} + +t_int *vinlet_perform(t_int *w) +{ + t_vinlet *x = (t_vinlet *)(w[1]); + t_float *out = (t_float *)(w[2]); + int n = (int)(w[3]); + t_float *in = x->x_read; + while (n--) *out++ = *in++; + if (in == x->x_endbuf) in = x->x_buf; + x->x_read = in; + return (w+4); +} + +static void vinlet_dsp(t_vinlet *x, t_signal **sp) +{ + t_signal *outsig; + /* no buffer means we're not a signal inlet */ + if (!x->x_buf) + return; + outsig = sp[0]; + if (x->x_directsignal) + { + signal_setborrowed(sp[0], x->x_directsignal); + } + else + { + dsp_add(vinlet_perform, 3, x, outsig->s_vec, outsig->s_vecsize); + x->x_read = x->x_buf; + } +} + + /* prolog code: loads buffer from parent patch */ +t_int *vinlet_doprolog(t_int *w) +{ + t_vinlet *x = (t_vinlet *)(w[1]); + t_float *in = (t_float *)(w[2]); + int n = (int)(w[3]); + t_float *out = x->x_fill; + if (out == x->x_endbuf) + { + t_float *f1 = x->x_buf, *f2 = x->x_buf + x->x_hop; + int nshift = x->x_bufsize - x->x_hop; + out -= x->x_hop; + while (nshift--) *f1++ = *f2++; + } + + while (n--) *out++ = *in++; + x->x_fill = out; + return (w+4); +} + +int inlet_getsignalindex(t_inlet *x); + + /* set up prolog DSP code */ +void vinlet_dspprolog(struct _vinlet *x, t_signal **parentsigs, + int myvecsize, int calcsize, int phase, int period, int frequency, + int downsample, int upsample, int reblock, int switched) +{ + t_signal *insig, *outsig; + /* no buffer means we're not a signal inlet */ + if (!x->x_buf) + return; + x->x_updown.downsample = downsample; + x->x_updown.upsample = upsample; + + /* if the "reblock" flag is set, arrange to copy data in from the + parent. */ + if (reblock) + { + int parentvecsize, bufsize, oldbufsize, prologphase; + int re_parentvecsize; /* resampled parentvectorsize */ + /* this should never happen: */ + if (!x->x_buf) return; + + /* the prolog code counts from 0 to period-1; the + phase is backed up by one so that AFTER the prolog code + runs, the "x_fill" phase is in sync with the "x_read" phase. */ + prologphase = (phase - 1) & (period - 1); + if (parentsigs) + { + insig = parentsigs[inlet_getsignalindex(x->x_inlet)]; + parentvecsize = insig->s_vecsize; + re_parentvecsize = parentvecsize * upsample / downsample; + } + else + { + insig = 0; + parentvecsize = 1; + re_parentvecsize = 1; + } + + bufsize = re_parentvecsize; + if (bufsize < myvecsize) bufsize = myvecsize; + if (bufsize != (oldbufsize = x->x_bufsize)) + { + t_float *buf = x->x_buf; + t_freebytes(buf, oldbufsize * sizeof(*buf)); + buf = (t_float *)t_getbytes(bufsize * sizeof(*buf)); + memset((char *)buf, 0, bufsize * sizeof(*buf)); + x->x_bufsize = bufsize; + x->x_endbuf = buf + bufsize; + x->x_buf = buf; + } + if (parentsigs) + { + x->x_hop = period * re_parentvecsize; + + x->x_fill = x->x_endbuf - + (x->x_hop - prologphase * re_parentvecsize); + + if (upsample * downsample == 1) + dsp_add(vinlet_doprolog, 3, x, insig->s_vec, + re_parentvecsize); + else { + int method = (x->x_updown.method == 3? + (pd_compatibilitylevel < 44 ? 0 : 1) : x->x_updown.method); + resamplefrom_dsp(&x->x_updown, insig->s_vec, parentvecsize, + re_parentvecsize, method); + dsp_add(vinlet_doprolog, 3, x, x->x_updown.s_vec, + re_parentvecsize); + } + + /* if the input signal's reference count is zero, we have + to free it here because we didn't in ugen_doit(). */ + if (!insig->s_refcount) + signal_makereusable(insig); + } + else memset((char *)(x->x_buf), 0, bufsize * sizeof(*x->x_buf)); + x->x_directsignal = 0; + } + else + { + /* no reblocking; in this case our output signal is "borrowed" + and merely needs to be pointed to the real one. */ + x->x_directsignal = parentsigs[inlet_getsignalindex(x->x_inlet)]; + } +} + +static void *vinlet_newsig(t_symbol *s) +{ + t_vinlet *x = (t_vinlet *)pd_new(vinlet_class); + x->x_canvas = canvas_getcurrent(); + x->x_inlet = canvas_addinlet(x->x_canvas, &x->x_obj.ob_pd, &s_signal); + x->x_endbuf = x->x_buf = (t_float *)getbytes(0); + x->x_bufsize = 0; + x->x_directsignal = 0; + outlet_new(&x->x_obj, &s_signal); + + resample_init(&x->x_updown); + + /* this should be though over: + * it might prove hard to provide consistency between labeled up- & downsampling methods + * maybe indices would be better... + * + * up till now we provide several upsampling methods and 1 single downsampling method (no filtering !) + */ + if (s == gensym("hold")) + x->x_updown.method=1; /* up: sample and hold */ + else if (s == gensym("lin") || s == gensym("linear")) + x->x_updown.method=2; /* up: linear interpolation */ + else if (s == gensym("pad")) + x->x_updown.method=0; /* up: zero-padding */ + else x->x_updown.method=3; /* sample/hold unless version<0.44 */ + + return (x); +} + +static void vinlet_setup(void) +{ + vinlet_class = class_new(gensym("inlet"), (t_newmethod)vinlet_new, + (t_method)vinlet_free, sizeof(t_vinlet), CLASS_NOINLET, A_DEFSYM, 0); + class_addcreator((t_newmethod)vinlet_newsig, gensym("inlet~"), A_DEFSYM, 0); + class_addbang(vinlet_class, vinlet_bang); + class_addpointer(vinlet_class, vinlet_pointer); + class_addfloat(vinlet_class, vinlet_float); + class_addsymbol(vinlet_class, vinlet_symbol); + class_addlist(vinlet_class, vinlet_list); + class_addanything(vinlet_class, vinlet_anything); + class_addmethod(vinlet_class, (t_method)vinlet_dsp, + gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(vinlet_class, gensym("pd")); +} + +/* ------------------------- voutlet -------------------------- */ + +t_class *voutlet_class; + +typedef struct _voutlet +{ + t_object x_obj; + t_canvas *x_canvas; + t_outlet *x_parentoutlet; + int x_bufsize; + t_sample *x_buf; /* signal buffer; zero if not a signal */ + t_sample *x_endbuf; + t_sample *x_empty; /* next to read out of buffer in epilog code */ + t_sample *x_write; /* next to write in to buffer */ + int x_hop; /* hopsize */ + /* vice versa from the inlet, if we don't block, this holds the + parent's outlet signal, valid between the prolog and the dsp setup + routines. */ + t_signal *x_directsignal; + /* and here's a flag indicating that we aren't blocked but have to + do a copy (because we're switched). */ + char x_justcopyout; + t_resample x_updown; +} t_voutlet; + +static void *voutlet_new(t_symbol *s) +{ + t_voutlet *x = (t_voutlet *)pd_new(voutlet_class); + x->x_canvas = canvas_getcurrent(); + x->x_parentoutlet = canvas_addoutlet(x->x_canvas, &x->x_obj.ob_pd, 0); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, 0, 0); + x->x_bufsize = 0; + x->x_buf = 0; + return (x); +} + +static void voutlet_bang(t_voutlet *x) +{ + outlet_bang(x->x_parentoutlet); +} + +static void voutlet_pointer(t_voutlet *x, t_gpointer *gp) +{ + outlet_pointer(x->x_parentoutlet, gp); +} + +static void voutlet_float(t_voutlet *x, t_float f) +{ + outlet_float(x->x_parentoutlet, f); +} + +static void voutlet_symbol(t_voutlet *x, t_symbol *s) +{ + outlet_symbol(x->x_parentoutlet, s); +} + +static void voutlet_list(t_voutlet *x, t_symbol *s, int argc, t_atom *argv) +{ + outlet_list(x->x_parentoutlet, s, argc, argv); +} + +static void voutlet_anything(t_voutlet *x, t_symbol *s, int argc, t_atom *argv) +{ + outlet_anything(x->x_parentoutlet, s, argc, argv); +} + +static void voutlet_free(t_voutlet *x) +{ + canvas_rmoutlet(x->x_canvas, x->x_parentoutlet); + if (x->x_buf) + t_freebytes(x->x_buf, x->x_bufsize * sizeof(*x->x_buf)); + resample_free(&x->x_updown); +} + +t_outlet *voutlet_getit(t_pd *x) +{ + if (pd_class(x) != voutlet_class) bug("voutlet_getit"); + return (((t_voutlet *)x)->x_parentoutlet); +} + +/* ------------------------- signal outlet -------------------------- */ + +int voutlet_issignal(t_voutlet *x) +{ + return (x->x_buf != 0); +} + + /* LATER optimize for non-overlapped case where the "+=" isn't needed */ +t_int *voutlet_perform(t_int *w) +{ + t_voutlet *x = (t_voutlet *)(w[1]); + t_float *in = (t_float *)(w[2]); + int n = (int)(w[3]); + t_sample *out = x->x_write, *outwas = out; + while (n--) + { + *out++ += *in++; + if (out == x->x_endbuf) out = x->x_buf; + } + outwas += x->x_hop; + if (outwas >= x->x_endbuf) outwas = x->x_buf; + x->x_write = outwas; + return (w+4); +} + + /* epilog code for blocking: write buffer to parent patch */ +static t_int *voutlet_doepilog(t_int *w) +{ + t_voutlet *x = (t_voutlet *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + + int n = (int)(w[3]); + t_sample *in = x->x_empty; + if (x->x_updown.downsample != x->x_updown.upsample) + out = x->x_updown.s_vec; + for (; n--; in++) *out++ = *in, *in = 0; + if (in == x->x_endbuf) in = x->x_buf; + x->x_empty = in; + return (w+4); +} + +static t_int *voutlet_doepilog_resampling(t_int *w) +{ + t_voutlet *x = (t_voutlet *)(w[1]); + int n = (int)(w[2]); + t_sample *in = x->x_empty; + t_sample *out = x->x_updown.s_vec; + for (; n--; in++) *out++ = *in, *in = 0; + if (in == x->x_endbuf) in = x->x_buf; + x->x_empty = in; + return (w+3); +} + +int outlet_getsignalindex(t_outlet *x); + + /* prolog for outlets -- store pointer to the outlet on the + parent, which, if "reblock" is false, will want to refer + back to whatever we see on our input during the "dsp" method + called later. */ +void voutlet_dspprolog(struct _voutlet *x, t_signal **parentsigs, + int myvecsize, int calcsize, int phase, int period, int frequency, + int downsample, int upsample, int reblock, int switched) +{ + /* no buffer means we're not a signal outlet */ + if (!x->x_buf) + return; + x->x_updown.downsample=downsample; + x->x_updown.upsample=upsample; + x->x_justcopyout = (switched && !reblock); + if (reblock) + { + x->x_directsignal = 0; + } + else + { + if (!parentsigs) bug("voutlet_dspprolog"); + x->x_directsignal = + parentsigs[outlet_getsignalindex(x->x_parentoutlet)]; + } +} + +static void voutlet_dsp(t_voutlet *x, t_signal **sp) +{ + t_signal *insig; + if (!x->x_buf) return; + insig = sp[0]; + if (x->x_justcopyout) + dsp_add_copy(insig->s_vec, x->x_directsignal->s_vec, insig->s_n); + else if (x->x_directsignal) + { + /* if we're just going to make the signal available on the + parent patch, hand it off to the parent signal. */ + /* this is done elsewhere--> sp[0]->s_refcount++; */ + signal_setborrowed(x->x_directsignal, sp[0]); + } + else + dsp_add(voutlet_perform, 3, x, insig->s_vec, insig->s_n); +} + + /* set up epilog DSP code. If we're reblocking, this is the + time to copy the samples out to the containing object's outlets. + If we aren't reblocking, there's nothing to do here. */ +void voutlet_dspepilog(struct _voutlet *x, t_signal **parentsigs, + int myvecsize, int calcsize, int phase, int period, int frequency, + int downsample, int upsample, int reblock, int switched) +{ + if (!x->x_buf) return; /* this shouldn't be necesssary... */ + x->x_updown.downsample=downsample; + x->x_updown.upsample=upsample; + if (reblock) + { + t_signal *insig, *outsig; + int parentvecsize, bufsize, oldbufsize; + int re_parentvecsize; + int bigperiod, epilogphase, blockphase; + if (parentsigs) + { + outsig = parentsigs[outlet_getsignalindex(x->x_parentoutlet)]; + parentvecsize = outsig->s_vecsize; + re_parentvecsize = parentvecsize * upsample / downsample; + } + else + { + outsig = 0; + parentvecsize = 1; + re_parentvecsize = 1; + } + bigperiod = myvecsize/re_parentvecsize; + if (!bigperiod) bigperiod = 1; + epilogphase = phase & (bigperiod - 1); + blockphase = (phase + period - 1) & (bigperiod - 1) & (- period); + bufsize = re_parentvecsize; + if (bufsize < myvecsize) bufsize = myvecsize; + if (bufsize != (oldbufsize = x->x_bufsize)) + { + t_sample *buf = x->x_buf; + t_freebytes(buf, oldbufsize * sizeof(*buf)); + buf = (t_sample *)t_getbytes(bufsize * sizeof(*buf)); + memset((char *)buf, 0, bufsize * sizeof(*buf)); + x->x_bufsize = bufsize; + x->x_endbuf = buf + bufsize; + x->x_buf = buf; + } + if (re_parentvecsize * period > bufsize) bug("voutlet_dspepilog"); + x->x_write = x->x_buf + re_parentvecsize * blockphase; + if (x->x_write == x->x_endbuf) x->x_write = x->x_buf; + if (period == 1 && frequency > 1) + x->x_hop = re_parentvecsize / frequency; + else x->x_hop = period * re_parentvecsize; + /* post("phase %d, block %d, parent %d", phase & 63, + parentvecsize * blockphase, parentvecsize * epilogphase); */ + if (parentsigs) + { + /* set epilog pointer and schedule it */ + x->x_empty = x->x_buf + re_parentvecsize * epilogphase; + if (upsample * downsample == 1) + dsp_add(voutlet_doepilog, 3, x, outsig->s_vec, + re_parentvecsize); + else + { + int method = (x->x_updown.method == 3? + (pd_compatibilitylevel < 44 ? 0 : 1) : x->x_updown.method); + dsp_add(voutlet_doepilog_resampling, 2, x, re_parentvecsize); + resampleto_dsp(&x->x_updown, outsig->s_vec, re_parentvecsize, + parentvecsize, method); + } + } + } + /* if we aren't blocked but we are switched, the epilog code just + copies zeros to the output. In this case the blocking code actually + jumps over the epilog if the block is running. */ + else if (switched) + { + if (parentsigs) + { + t_signal *outsig = + parentsigs[outlet_getsignalindex(x->x_parentoutlet)]; + dsp_add_zero(outsig->s_vec, outsig->s_n); + } + } +} + +static void *voutlet_newsig(t_symbol *s) +{ + t_voutlet *x = (t_voutlet *)pd_new(voutlet_class); + x->x_canvas = canvas_getcurrent(); + x->x_parentoutlet = canvas_addoutlet(x->x_canvas, + &x->x_obj.ob_pd, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + x->x_endbuf = x->x_buf = (t_sample *)getbytes(0); + x->x_bufsize = 0; + + resample_init(&x->x_updown); + + /* this should be though over: + * it might prove hard to provide consistency between labeled up- & downsampling methods + * maybe indices would be better... + * + * up till now we provide several upsampling methods and 1 single downsampling method (no filtering !) + */ + if (s == gensym("hold"))x->x_updown.method=1; /* up: sample and hold */ + else if (s == gensym("lin"))x->x_updown.method=2; /* up: linear interpolation */ + else if (s == gensym("linear"))x->x_updown.method=2; /* up: linear interpolation */ + else if (s == gensym("pad"))x->x_updown.method=0; /* up: zero pad */ + else x->x_updown.method=3; /* up: zero-padding; down: ignore samples inbetween */ + + return (x); +} + + +static void voutlet_setup(void) +{ + voutlet_class = class_new(gensym("outlet"), (t_newmethod)voutlet_new, + (t_method)voutlet_free, sizeof(t_voutlet), CLASS_NOINLET, A_DEFSYM, 0); + class_addcreator((t_newmethod)voutlet_newsig, gensym("outlet~"), A_DEFSYM, 0); + class_addbang(voutlet_class, voutlet_bang); + class_addpointer(voutlet_class, voutlet_pointer); + class_addfloat(voutlet_class, (t_method)voutlet_float); + class_addsymbol(voutlet_class, voutlet_symbol); + class_addlist(voutlet_class, voutlet_list); + class_addanything(voutlet_class, voutlet_anything); + class_addmethod(voutlet_class, (t_method)voutlet_dsp, + gensym("dsp"), A_CANT, 0); + class_sethelpsymbol(voutlet_class, gensym("pd")); +} + + +/* ---------------------------- overall setup ----------------------------- */ + +void g_io_setup(void) +{ + vinlet_setup(); + voutlet_setup(); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_mycanvas.c b/ports/camomile/source/LibPd/pure-data/src/g_mycanvas.c new file mode 100644 index 00000000..058a4367 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_mycanvas.c @@ -0,0 +1,406 @@ +/* Copyright (c) 1997-1999 Miller Puckette. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */ +/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */ + +#include +#include +#include +#include +#include "m_pd.h" +#include "g_canvas.h" + +#include "g_all_guis.h" +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +/* ---------- cnv my gui-canvas for a window ---------------- */ + +t_widgetbehavior my_canvas_widgetbehavior; +static t_class *my_canvas_class; + +/* widget helper functions */ + +void my_canvas_draw_new(t_my_canvas *x, t_glist *glist) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int offset = (IEMGUI_ZOOM(x) > 1 ? IEMGUI_ZOOM(x) : 0); /* keep zoomed border inside visible area */ + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%06x -outline #%06x -tags %lxRECT\n", + canvas, xpos, ypos, + xpos + x->x_vis_w * IEMGUI_ZOOM(x), + ypos + x->x_vis_h * IEMGUI_ZOOM(x), + x->x_gui.x_bcol, x->x_gui.x_bcol, x); + sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -outline #%06x -tags %lxBASE\n", + canvas, xpos + offset, ypos + offset, + xpos + offset + x->x_gui.x_w, ypos + offset + x->x_gui.x_h, + IEMGUI_ZOOM(x), x->x_gui.x_bcol, x); + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \ + -font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n", + canvas, + xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x), + (strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""), + x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + x->x_gui.x_lcol, x); +} + +void my_canvas_draw_move(t_my_canvas *x, t_glist *glist) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int offset = (IEMGUI_ZOOM(x) > 1 ? IEMGUI_ZOOM(x) : 0); + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c coords %lxRECT %d %d %d %d\n", + canvas, x, xpos, ypos, + xpos + x->x_vis_w * IEMGUI_ZOOM(x), + ypos + x->x_vis_h * IEMGUI_ZOOM(x)); + sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n", + canvas, x, xpos + offset, ypos + offset, + xpos + offset + x->x_gui.x_w, ypos + offset + x->x_gui.x_h); + sys_vgui(".x%lx.c coords %lxLABEL %d %d\n", + canvas, x, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x)); +} + +void my_canvas_draw_erase(t_my_canvas* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c delete %lxBASE\n", canvas, x); + sys_vgui(".x%lx.c delete %lxRECT\n", canvas, x); + sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x); +} + +void my_canvas_draw_config(t_my_canvas* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c itemconfigure %lxRECT -fill #%06x -outline #%06x\n", canvas, x, + x->x_gui.x_bcol, x->x_gui.x_bcol); + sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, + (x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_bcol)); + sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n", + canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + x->x_gui.x_lcol, + (strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : "")); +} + +void my_canvas_draw_select(t_my_canvas* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + if(x->x_gui.x_fsf.x_selected) + { + sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + } + else + { + sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, x->x_gui.x_bcol); + } +} + +void my_canvas_draw(t_my_canvas *x, t_glist *glist, int mode) +{ + if(mode == IEM_GUI_DRAW_MODE_MOVE) + my_canvas_draw_move(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_NEW) + my_canvas_draw_new(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_SELECT) + my_canvas_draw_select(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_ERASE) + my_canvas_draw_erase(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_CONFIG) + my_canvas_draw_config(x, glist); +} + +/* ------------------------ cnv widgetbehaviour----------------------------- */ + +static void my_canvas_getrect(t_gobj *z, t_glist *glist, int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_my_canvas *x = (t_my_canvas *)z; + + *xp1 = text_xpix(&x->x_gui.x_obj, glist); + *yp1 = text_ypix(&x->x_gui.x_obj, glist); + *xp2 = *xp1 + x->x_gui.x_w; + *yp2 = *yp1 + x->x_gui.x_h; +} + +static void my_canvas_save(t_gobj *z, t_binbuf *b) +{ + t_my_canvas *x = (t_my_canvas *)z; + t_symbol *bflcol[3]; + t_symbol *srl[3]; + + iemgui_save(&x->x_gui, srl, bflcol); + binbuf_addv(b, "ssiisiiisssiiiissi", gensym("#X"),gensym("obj"), + (int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix, + gensym("cnv"), x->x_gui.x_w/IEMGUI_ZOOM(x), x->x_vis_w, x->x_vis_h, + srl[0], srl[1], srl[2], x->x_gui.x_ldx, x->x_gui.x_ldy, + iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize, + bflcol[0], bflcol[2], iem_symargstoint(&x->x_gui.x_isa)); + binbuf_addv(b, ";"); +} + +static void my_canvas_properties(t_gobj *z, t_glist *owner) +{ + t_my_canvas *x = (t_my_canvas *)z; + char buf[800]; + t_symbol *srl[3]; + + iemgui_properties(&x->x_gui, srl); + sprintf(buf, "pdtk_iemgui_dialog %%s |cnv| \ + ------selectable_dimensions(pix):------ %d %d size: 0.0 0.0 empty \ + ------visible_rectangle(pix)(pix):------ %d width: %d height: %d \ + %d empty empty %d %d empty %d \ + %s %s \ + %s %d %d \ + %d %d \ + #%06x none #%06x\n", + x->x_gui.x_w/IEMGUI_ZOOM(x), 1, + x->x_vis_w, x->x_vis_h, 0,/*no_schedule*/ + -1, -1, -1, -1,/*no linlog, no init, no multi*/ + srl[0]->s_name, srl[1]->s_name, + srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy, + x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize, + 0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_lcol); + gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf); +} + +static void my_canvas_get_pos(t_my_canvas *x) +{ + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + { + x->x_at[0].a_w.w_float = text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist)/IEMGUI_ZOOM(x); + x->x_at[1].a_w.w_float = text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist)/IEMGUI_ZOOM(x); + pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at); + } +} + +static void my_canvas_dialog(t_my_canvas *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *srl[3]; + int a = atom_getfloatarg(0, argc, argv); + int w = atom_getfloatarg(2, argc, argv); + int h = atom_getfloatarg(3, argc, argv); + int sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv); + + x->x_gui.x_isa.x_loadinit = 0; + if(a < 1) + a = 1; + x->x_gui.x_w = a * IEMGUI_ZOOM(x); + x->x_gui.x_h = x->x_gui.x_w; + if(w < 1) + w = 1; + x->x_vis_w = w; + if(h < 1) + h = 1; + x->x_vis_h = h; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); +} + +static void my_canvas_size(t_my_canvas *x, t_symbol *s, int ac, t_atom *av) +{ + int i = atom_getfloatarg(0, ac, av); + + if(i < 1) + i = 1; + x->x_gui.x_w = i*IEMGUI_ZOOM(x); + x->x_gui.x_h = x->x_gui.x_w; + iemgui_size((void *)x, &x->x_gui); +} + +static void my_canvas_delta(t_my_canvas *x, t_symbol *s, int ac, t_atom *av) +{iemgui_delta((void *)x, &x->x_gui, s, ac, av);} + +static void my_canvas_pos(t_my_canvas *x, t_symbol *s, int ac, t_atom *av) +{iemgui_pos((void *)x, &x->x_gui, s, ac, av);} + +static void my_canvas_vis_size(t_my_canvas *x, t_symbol *s, int ac, t_atom *av) +{ + int i; + + i = atom_getfloatarg(0, ac, av); + if(i < 1) + i = 1; + x->x_vis_w = i; + if(ac > 1) + { + i = atom_getfloatarg(1, ac, av); + if(i < 1) + i = 1; + } + x->x_vis_h = i; + if(glist_isvisible(x->x_gui.x_glist)) + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); +} + +static void my_canvas_color(t_my_canvas *x, t_symbol *s, int ac, t_atom *av) +{iemgui_color((void *)x, &x->x_gui, s, ac, av);} + +static void my_canvas_send(t_my_canvas *x, t_symbol *s) +{iemgui_send(x, &x->x_gui, s);} + +static void my_canvas_receive(t_my_canvas *x, t_symbol *s) +{iemgui_receive(x, &x->x_gui, s);} + +static void my_canvas_label(t_my_canvas *x, t_symbol *s) +{iemgui_label((void *)x, &x->x_gui, s);} + +static void my_canvas_label_pos(t_my_canvas *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);} + +static void my_canvas_label_font(t_my_canvas *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);} + +static void *my_canvas_new(t_symbol *s, int argc, t_atom *argv) +{ + t_my_canvas *x = (t_my_canvas *)pd_new(my_canvas_class); + int a = IEM_GUI_DEFAULTSIZE, w = 100, h = 60; + int ldx = 20, ldy = 12, f = 2, i = 0; + int fs = 14; + char str[144]; + + iem_inttosymargs(&x->x_gui.x_isa, 0); + iem_inttofstyle(&x->x_gui.x_fsf, 0); + + x->x_gui.x_bcol = 0xE0E0E0; + x->x_gui.x_fcol = 0x00; + x->x_gui.x_lcol = 0x404040; + + if(((argc >= 10)&&(argc <= 13)) + &&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)&&IS_A_FLOAT(argv,2)) + { + a = atom_getfloatarg(0, argc, argv); + w = atom_getfloatarg(1, argc, argv); + h = atom_getfloatarg(2, argc, argv); + } + if((argc >= 12)&&(IS_A_SYMBOL(argv,3)||IS_A_FLOAT(argv,3))&&(IS_A_SYMBOL(argv,4)||IS_A_FLOAT(argv,4))) + { + i = 2; + iemgui_new_getnames(&x->x_gui, 3, argv); + } + else if((argc == 11)&&(IS_A_SYMBOL(argv,3)||IS_A_FLOAT(argv,3))) + { + i = 1; + iemgui_new_getnames(&x->x_gui, 3, argv); + } + else iemgui_new_getnames(&x->x_gui, 3, 0); + + if(((argc >= 10)&&(argc <= 13)) + &&(IS_A_SYMBOL(argv,i+3)||IS_A_FLOAT(argv,i+3))&&IS_A_FLOAT(argv,i+4) + &&IS_A_FLOAT(argv,i+5)&&IS_A_FLOAT(argv,i+6) + &&IS_A_FLOAT(argv,i+7)) + { + /* disastrously, the "label" sits in a different part of the + message. So we have to track its location separately (in + the slot x_labelbindex) and initialize it specially here. */ + iemgui_new_dogetname(&x->x_gui, i+3, argv); + x->x_gui.x_labelbindex = i+4; + ldx = atom_getfloatarg(i+4, argc, argv); + ldy = atom_getfloatarg(i+5, argc, argv); + iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(i+6, argc, argv)); + fs = atom_getfloatarg(i+7, argc, argv); + iemgui_all_loadcolors(&x->x_gui, argv+i+8, 0, argv+i+9); + } + if((argc == 13)&&IS_A_FLOAT(argv,i+10)) + { + iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(i+10, argc, argv)); + } + x->x_gui.x_draw = (t_iemfunptr)my_canvas_draw; + x->x_gui.x_fsf.x_snd_able = 1; + x->x_gui.x_fsf.x_rcv_able = 1; + x->x_gui.x_glist = (t_glist *)canvas_getcurrent(); + if (!strcmp(x->x_gui.x_snd->s_name, "empty")) + x->x_gui.x_fsf.x_snd_able = 0; + if (!strcmp(x->x_gui.x_rcv->s_name, "empty")) + x->x_gui.x_fsf.x_rcv_able = 0; + if(a < 1) + a = 1; + x->x_gui.x_w = a; + x->x_gui.x_h = x->x_gui.x_w; + if(w < 1) + w = 1; + x->x_vis_w = w; + if(h < 1) + h = 1; + x->x_vis_h = h; + if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica"); + else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times"); + else { x->x_gui.x_fsf.x_font_style = 0; + strcpy(x->x_gui.x_font, sys_font); } + if (x->x_gui.x_fsf.x_rcv_able) + pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + x->x_gui.x_ldx = ldx; + x->x_gui.x_ldy = ldy; + if(fs < 4) + fs = 4; + x->x_gui.x_fontsize = fs; + x->x_at[0].a_type = A_FLOAT; + x->x_at[1].a_type = A_FLOAT; + iemgui_verify_snd_ne_rcv(&x->x_gui); + iemgui_newzoom(&x->x_gui); + return (x); +} + +static void my_canvas_ff(t_my_canvas *x) +{ + if(x->x_gui.x_fsf.x_rcv_able) + pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + gfxstub_deleteforkey(x); +} + +void g_mycanvas_setup(void) +{ + my_canvas_class = class_new(gensym("cnv"), (t_newmethod)my_canvas_new, + (t_method)my_canvas_ff, sizeof(t_my_canvas), CLASS_NOINLET, A_GIMME, 0); + class_addcreator((t_newmethod)my_canvas_new, gensym("my_canvas"), A_GIMME, 0); + class_addmethod(my_canvas_class, (t_method)my_canvas_dialog, + gensym("dialog"), A_GIMME, 0); + class_addmethod(my_canvas_class, (t_method)my_canvas_size, + gensym("size"), A_GIMME, 0); + class_addmethod(my_canvas_class, (t_method)my_canvas_delta, + gensym("delta"), A_GIMME, 0); + class_addmethod(my_canvas_class, (t_method)my_canvas_pos, + gensym("pos"), A_GIMME, 0); + class_addmethod(my_canvas_class, (t_method)my_canvas_vis_size, + gensym("vis_size"), A_GIMME, 0); + class_addmethod(my_canvas_class, (t_method)my_canvas_color, + gensym("color"), A_GIMME, 0); + class_addmethod(my_canvas_class, (t_method)my_canvas_send, + gensym("send"), A_DEFSYM, 0); + class_addmethod(my_canvas_class, (t_method)my_canvas_receive, + gensym("receive"), A_DEFSYM, 0); + class_addmethod(my_canvas_class, (t_method)my_canvas_label, + gensym("label"), A_DEFSYM, 0); + class_addmethod(my_canvas_class, (t_method)my_canvas_label_pos, + gensym("label_pos"), A_GIMME, 0); + class_addmethod(my_canvas_class, (t_method)my_canvas_label_font, + gensym("label_font"), A_GIMME, 0); + class_addmethod(my_canvas_class, (t_method)my_canvas_get_pos, + gensym("get_pos"), 0); + class_addmethod(my_canvas_class, (t_method)iemgui_zoom, + gensym("zoom"), A_CANT, 0); + my_canvas_widgetbehavior.w_getrectfn = my_canvas_getrect; + my_canvas_widgetbehavior.w_displacefn = iemgui_displace; + my_canvas_widgetbehavior.w_selectfn = iemgui_select; + my_canvas_widgetbehavior.w_activatefn = NULL; + my_canvas_widgetbehavior.w_deletefn = iemgui_delete; + my_canvas_widgetbehavior.w_visfn = iemgui_vis; + my_canvas_widgetbehavior.w_clickfn = NULL; + class_setwidget(my_canvas_class, &my_canvas_widgetbehavior); + class_sethelpsymbol(my_canvas_class, gensym("my_canvas")); + class_setsavefn(my_canvas_class, my_canvas_save); + class_setpropertiesfn(my_canvas_class, my_canvas_properties); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_numbox.c b/ports/camomile/source/LibPd/pure-data/src/g_numbox.c new file mode 100644 index 00000000..fabcd49a --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_numbox.c @@ -0,0 +1,926 @@ +/* Copyright (c) 1997-1999 Miller Puckette. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* my_numbox.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */ + +#include +#include +#include +#include +#include "m_pd.h" +#include "g_canvas.h" + +#include "g_all_guis.h" +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +#define MINDIGITS 1 +#define MINFONT 4 + +/*------------------ global functions -------------------------*/ + +static void my_numbox_key(void *z, t_floatarg fkey); +static void my_numbox_draw_update(t_gobj *client, t_glist *glist); + +/* ------------ nbx gui-my number box ----------------------- */ + +t_widgetbehavior my_numbox_widgetbehavior; +static t_class *my_numbox_class; + +/* widget helper functions */ + +static void my_numbox_tick_reset(t_my_numbox *x) +{ + if(x->x_gui.x_fsf.x_change && x->x_gui.x_glist) + { + x->x_gui.x_fsf.x_change = 0; + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + } +} + +static void my_numbox_tick_wait(t_my_numbox *x) +{ + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); +} + +void my_numbox_clip(t_my_numbox *x) +{ + if(x->x_val < x->x_min) + x->x_val = x->x_min; + if(x->x_val > x->x_max) + x->x_val = x->x_max; +} + +void my_numbox_calc_fontwidth(t_my_numbox *x) +{ + int w, f = 31; + + if(x->x_gui.x_fsf.x_font_style == 1) + f = 27; + else if(x->x_gui.x_fsf.x_font_style == 2) + f = 25; + + w = x->x_gui.x_fontsize * f * x->x_numwidth; + w /= 36; + x->x_gui.x_w = (w + (x->x_gui.x_h/2)/IEMGUI_ZOOM(x) + 4) * IEMGUI_ZOOM(x); +} + +void my_numbox_ftoa(t_my_numbox *x) +{ + double f = x->x_val; + int bufsize, is_exp = 0, i, idecimal; + + sprintf(x->x_buf, "%g", f); + bufsize = (int)strlen(x->x_buf); + if(bufsize >= 5)/* if it is in exponential mode */ + { + i = bufsize - 4; + if((x->x_buf[i] == 'e') || (x->x_buf[i] == 'E')) + is_exp = 1; + } + if(bufsize > x->x_numwidth)/* if to reduce */ + { + if(is_exp) + { + if(x->x_numwidth <= 5) + { + x->x_buf[0] = (f < 0.0 ? '-' : '+'); + x->x_buf[1] = 0; + } + i = bufsize - 4; + for(idecimal = 0; idecimal < i; idecimal++) + if(x->x_buf[idecimal] == '.') + break; + if(idecimal > (x->x_numwidth - 4)) + { + x->x_buf[0] = (f < 0.0 ? '-' : '+'); + x->x_buf[1] = 0; + } + else + { + int new_exp_index = x->x_numwidth - 4; + int old_exp_index = bufsize - 4; + + for(i = 0; i < 4; i++, new_exp_index++, old_exp_index++) + x->x_buf[new_exp_index] = x->x_buf[old_exp_index]; + x->x_buf[x->x_numwidth] = 0; + } + } + else + { + for(idecimal = 0; idecimal < bufsize; idecimal++) + if(x->x_buf[idecimal] == '.') + break; + if(idecimal > x->x_numwidth) + { + x->x_buf[0] = (f < 0.0 ? '-' : '+'); + x->x_buf[1] = 0; + } + else + x->x_buf[x->x_numwidth] = 0; + } + } +} + +static void my_numbox_draw_update(t_gobj *client, t_glist *glist) +{ + t_my_numbox *x = (t_my_numbox *)client; + if(glist_isvisible(glist)) + { + if(x->x_gui.x_fsf.x_change) + { + if(x->x_buf[0]) + { + char *cp = x->x_buf; + int sl = (int)strlen(x->x_buf); + + x->x_buf[sl] = '>'; + x->x_buf[sl+1] = 0; + if(sl >= x->x_numwidth) + cp += sl - x->x_numwidth + 1; + sys_vgui(".x%lx.c itemconfigure %lxNUMBER -fill #%06x -text {%s} \n", + glist_getcanvas(glist), x, + IEM_GUI_COLOR_EDITED, cp); + x->x_buf[sl] = 0; + } + else + { + my_numbox_ftoa(x); + sys_vgui(".x%lx.c itemconfigure %lxNUMBER -fill #%06x -text {%s} \n", + glist_getcanvas(glist), x, + IEM_GUI_COLOR_EDITED, x->x_buf); + x->x_buf[0] = 0; + } + } + else + { + my_numbox_ftoa(x); + sys_vgui(".x%lx.c itemconfigure %lxNUMBER -fill #%06x -text {%s} \n", + glist_getcanvas(glist), x, + (x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_fcol), + x->x_buf); + x->x_buf[0] = 0; + } + } +} + +static void my_numbox_draw_new(t_my_numbox *x, t_glist *glist) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int w = x->x_gui.x_w, half = x->x_gui.x_h/2; + int d = IEMGUI_ZOOM(x) + x->x_gui.x_h/(34*IEMGUI_ZOOM(x)); + int corner = x->x_gui.x_h/4; + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c create polygon %d %d %d %d %d %d %d %d %d %d %d %d " + "-width %d -outline #%06x -fill #%06x -tags %lxBASE1\n", + canvas, + xpos, ypos, + xpos + w - corner, ypos, + xpos + w, ypos + corner, + xpos + w, ypos + x->x_gui.x_h, + xpos, ypos + x->x_gui.x_h, + xpos, ypos, + IEMGUI_ZOOM(x), IEM_GUI_COLOR_NORMAL, x->x_gui.x_bcol, x); + sys_vgui(".x%lx.c create line %d %d %d %d %d %d -width %d -fill #%06x -tags %lxBASE2\n", + canvas, + xpos + IEMGUI_ZOOM(x), ypos + IEMGUI_ZOOM(x), + xpos + half, ypos + half, + xpos + IEMGUI_ZOOM(x), ypos + x->x_gui.x_h - IEMGUI_ZOOM(x), + IEMGUI_ZOOM(x), x->x_gui.x_fcol, x); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n", + canvas, + xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh, + xpos + iow, ypos + x->x_gui.x_h, + x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n", + canvas, + xpos, ypos, + xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh, + x, 0); + my_numbox_ftoa(x); + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w -font {{%s} -%d %s} -fill #%06x -tags %lxNUMBER\n", + canvas, xpos + half + 2*IEMGUI_ZOOM(x), ypos + half + d, + x->x_buf, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), + sys_fontweight, (x->x_gui.x_fsf.x_change ? IEM_GUI_COLOR_EDITED : x->x_gui.x_fcol), x); + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w -font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n", + canvas, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x), + (strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""), + x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + x->x_gui.x_lcol, x); +} + +static void my_numbox_draw_move(t_my_numbox *x, t_glist *glist) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int w = x->x_gui.x_w, half = x->x_gui.x_h/2; + int d = IEMGUI_ZOOM(x) + x->x_gui.x_h / (34 * IEMGUI_ZOOM(x)); + int corner = x->x_gui.x_h/4; + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c coords %lxBASE1 %d %d %d %d %d %d %d %d %d %d %d %d\n", + canvas, x, + xpos, ypos, + xpos + w - corner, ypos, + xpos + w, ypos + corner, + xpos + w, ypos + x->x_gui.x_h, + xpos, ypos + x->x_gui.x_h, + xpos, ypos); + sys_vgui(".x%lx.c coords %lxBASE2 %d %d %d %d %d %d\n", + canvas, x, + xpos + IEMGUI_ZOOM(x), ypos + IEMGUI_ZOOM(x), + xpos + half, ypos + half, + xpos + IEMGUI_ZOOM(x), ypos + x->x_gui.x_h - IEMGUI_ZOOM(x)); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n", + canvas, x, 0, + xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh, + xpos + iow, ypos + x->x_gui.x_h); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n", + canvas, x, 0, + xpos, ypos, + xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh); + sys_vgui(".x%lx.c coords %lxLABEL %d %d\n", + canvas, x, + xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x)); + sys_vgui(".x%lx.c coords %lxNUMBER %d %d\n", + canvas, x, xpos + half + 2*IEMGUI_ZOOM(x), ypos + half + d); +} + +static void my_numbox_draw_erase(t_my_numbox* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c delete %lxBASE1\n", canvas, x); + sys_vgui(".x%lx.c delete %lxBASE2\n", canvas, x); + sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x); + sys_vgui(".x%lx.c delete %lxNUMBER\n", canvas, x); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); +} + +static void my_numbox_draw_config(t_my_numbox* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n", + canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + (x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol), + strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name:""); + sys_vgui(".x%lx.c itemconfigure %lxNUMBER -font {{%s} -%d %s} -fill #%06x \n", + canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + (x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_fcol)); + sys_vgui(".x%lx.c itemconfigure %lxBASE1 -fill #%06x\n", canvas, + x, x->x_gui.x_bcol); + sys_vgui(".x%lx.c itemconfigure %lxBASE2 -fill #%06x\n", canvas, x, + (x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_fcol)); +} + +static void my_numbox_draw_io(t_my_numbox* x,t_glist* glist, int old_snd_rcv_flags) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able) { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n", + canvas, + xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh, + xpos + iow, ypos + x->x_gui.x_h, + x, 0); + /* keep these above outlet */ + sys_vgui(".x%lx.c raise %lxNUMBER %lxOUT%d\n", canvas, x, x, 0); + sys_vgui(".x%lx.c raise %lxLABEL %lxNUMBER\n", canvas, x, x); + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able) { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n", + canvas, + xpos, ypos, + xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh, + x, 0); + /* keep these above inlet */ + sys_vgui(".x%lx.c raise %lxNUMBER %lxIN%d\n", canvas, x, x, 0); + sys_vgui(".x%lx.c raise %lxLABEL %lxNUMBER\n", canvas, x, x); + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); +} + +static void my_numbox_draw_select(t_my_numbox *x, t_glist *glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + if(x->x_gui.x_fsf.x_selected) + { + if(x->x_gui.x_fsf.x_change) + { + x->x_gui.x_fsf.x_change = 0; + clock_unset(x->x_clock_reset); + x->x_buf[0] = 0; + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + } + sys_vgui(".x%lx.c itemconfigure %lxBASE1 -outline #%06x\n", + canvas, x, IEM_GUI_COLOR_SELECTED); + sys_vgui(".x%lx.c itemconfigure %lxBASE2 -fill #%06x\n", + canvas, x, IEM_GUI_COLOR_SELECTED); + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", + canvas, x, IEM_GUI_COLOR_SELECTED); + sys_vgui(".x%lx.c itemconfigure %lxNUMBER -fill #%06x\n", + canvas, x, IEM_GUI_COLOR_SELECTED); + } + else + { + sys_vgui(".x%lx.c itemconfigure %lxBASE1 -outline #%06x\n", + canvas, x, IEM_GUI_COLOR_NORMAL); + sys_vgui(".x%lx.c itemconfigure %lxBASE2 -fill #%06x\n", + canvas, x, x->x_gui.x_fcol); + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", + canvas, x, x->x_gui.x_lcol); + sys_vgui(".x%lx.c itemconfigure %lxNUMBER -fill #%06x\n", + canvas, x, x->x_gui.x_fcol); + } +} + +void my_numbox_draw(t_my_numbox *x, t_glist *glist, int mode) +{ + if(mode == IEM_GUI_DRAW_MODE_UPDATE) + sys_queuegui(x, glist, my_numbox_draw_update); + else if(mode == IEM_GUI_DRAW_MODE_MOVE) + my_numbox_draw_move(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_NEW) + my_numbox_draw_new(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_SELECT) + my_numbox_draw_select(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_ERASE) + my_numbox_draw_erase(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_CONFIG) + my_numbox_draw_config(x, glist); + else if(mode >= IEM_GUI_DRAW_MODE_IO) + my_numbox_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO); +} + +/* ------------------------ nbx widgetbehaviour----------------------------- */ + +static void my_numbox_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_my_numbox* x = (t_my_numbox*)z; + + *xp1 = text_xpix(&x->x_gui.x_obj, glist); + *yp1 = text_ypix(&x->x_gui.x_obj, glist); + *xp2 = *xp1 + x->x_gui.x_w; + *yp2 = *yp1 + x->x_gui.x_h; +} + +static void my_numbox_save(t_gobj *z, t_binbuf *b) +{ + t_my_numbox *x = (t_my_numbox *)z; + t_symbol *bflcol[3]; + t_symbol *srl[3]; + + iemgui_save(&x->x_gui, srl, bflcol); + if(x->x_gui.x_fsf.x_change) + { + x->x_gui.x_fsf.x_change = 0; + clock_unset(x->x_clock_reset); + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + } + binbuf_addv(b, "ssiisiiffiisssiiiisssfi", gensym("#X"), gensym("obj"), + (int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix, + gensym("nbx"), x->x_numwidth, x->x_gui.x_h/IEMGUI_ZOOM(x), + (t_float)x->x_min, (t_float)x->x_max, + x->x_lin0_log1, iem_symargstoint(&x->x_gui.x_isa), + srl[0], srl[1], srl[2], + x->x_gui.x_ldx, x->x_gui.x_ldy, + iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize, + bflcol[0], bflcol[1], bflcol[2], + x->x_val, x->x_log_height); + binbuf_addv(b, ";"); +} + +int my_numbox_check_minmax(t_my_numbox *x, double min, double max) +{ + int ret = 0; + + if(x->x_lin0_log1) + { + if((min == 0.0) && (max == 0.0)) + max = 1.0; + if(max > 0.0) + { + if(min <= 0.0) + min = 0.01 * max; + } + else + { + if(min > 0.0) + max = 0.01 * min; + } + } + x->x_min = min; + x->x_max = max; + if(x->x_val < x->x_min) + { + x->x_val = x->x_min; + ret = 1; + } + if(x->x_val > x->x_max) + { + x->x_val = x->x_max; + ret = 1; + } + if(x->x_lin0_log1) + x->x_k = exp(log(x->x_max/x->x_min) / (double)(x->x_log_height)); + else + x->x_k = 1.0; + return(ret); +} + +static void my_numbox_properties(t_gobj *z, t_glist *owner) +{ + t_my_numbox *x = (t_my_numbox *)z; + char buf[800]; + t_symbol *srl[3]; + + iemgui_properties(&x->x_gui, srl); + if(x->x_gui.x_fsf.x_change) + { + x->x_gui.x_fsf.x_change = 0; + clock_unset(x->x_clock_reset); + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + } + sprintf(buf, "pdtk_iemgui_dialog %%s |nbx| \ + -------dimensions(digits)(pix):------- %d %d width: %d %d height: \ + -----------output-range:----------- %g min: %g max: %d \ + %d lin log %d %d log-height: %d \ + %s %s \ + %s %d %d \ + %d %d \ + #%06x #%06x #%06x\n", + x->x_numwidth, MINDIGITS, x->x_gui.x_h/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE, + x->x_min, x->x_max, 0,/*no_schedule*/ + x->x_lin0_log1, x->x_gui.x_isa.x_loadinit, -1, + x->x_log_height, /*no multi, but iem-characteristic*/ + srl[0]->s_name, srl[1]->s_name, + srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy, + x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize, + 0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, + 0xffffff & x->x_gui.x_lcol); + gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf); +} + +static void my_numbox_bang(t_my_numbox *x) +{ + outlet_float(x->x_gui.x_obj.ob_outlet, x->x_val); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, x->x_val); +} + +static void my_numbox_dialog(t_my_numbox *x, t_symbol *s, int argc, + t_atom *argv) +{ + t_symbol *srl[3]; + int w = (int)atom_getfloatarg(0, argc, argv); + int h = (int)atom_getfloatarg(1, argc, argv); + double min = (double)atom_getfloatarg(2, argc, argv); + double max = (double)atom_getfloatarg(3, argc, argv); + int lilo = (int)atom_getfloatarg(4, argc, argv); + int log_height = (int)atom_getfloatarg(6, argc, argv); + int sr_flags; + + if(lilo != 0) lilo = 1; + x->x_lin0_log1 = lilo; + sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv); + if(w < MINDIGITS) + w = MINDIGITS; + x->x_numwidth = w; + if(h < IEM_GUI_MINSIZE) + h = IEM_GUI_MINSIZE; + x->x_gui.x_h = h * IEMGUI_ZOOM(x); + if(log_height < 10) + log_height = 10; + x->x_log_height = log_height; + my_numbox_calc_fontwidth(x); + /*if(my_numbox_check_minmax(x, min, max)) + my_numbox_bang(x);*/ + my_numbox_check_minmax(x, min, max); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x); +} + +static void my_numbox_motion(t_my_numbox *x, t_floatarg dx, t_floatarg dy) +{ + double k2 = 1.0; + + if(x->x_gui.x_fsf.x_finemoved) + k2 = 0.01; + if(x->x_lin0_log1) + x->x_val *= pow(x->x_k, -k2*dy); + else + x->x_val -= k2*dy; + my_numbox_clip(x); + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + my_numbox_bang(x); + clock_unset(x->x_clock_reset); +} + +static void my_numbox_click(t_my_numbox *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, + (t_glistmotionfn)my_numbox_motion, my_numbox_key, xpos, ypos); +} + +static int my_numbox_newclick(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_my_numbox* x = (t_my_numbox *)z; + + if(doit) + { + my_numbox_click( x, (t_floatarg)xpix, (t_floatarg)ypix, + (t_floatarg)shift, 0, (t_floatarg)alt); + if(shift) + x->x_gui.x_fsf.x_finemoved = 1; + else + x->x_gui.x_fsf.x_finemoved = 0; + if(!x->x_gui.x_fsf.x_change) + { + clock_delay(x->x_clock_wait, 50); + x->x_gui.x_fsf.x_change = 1; + clock_delay(x->x_clock_reset, 3000); + + x->x_buf[0] = 0; + } + else + { + x->x_gui.x_fsf.x_change = 0; + clock_unset(x->x_clock_reset); + x->x_buf[0] = 0; + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + } + } + return (1); +} + +static void my_numbox_set(t_my_numbox *x, t_floatarg f) +{ + if(x->x_val != f) + { + x->x_val = f; + my_numbox_clip(x); + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + } +} + +static void my_numbox_log_height(t_my_numbox *x, t_floatarg lh) +{ + if(lh < 10.0) + lh = 10.0; + x->x_log_height = (int)lh; + if(x->x_lin0_log1) + x->x_k = exp(log(x->x_max/x->x_min)/(double)(x->x_log_height)); + else + x->x_k = 1.0; +} + +static void my_numbox_float(t_my_numbox *x, t_floatarg f) +{ + my_numbox_set(x, f); + if(x->x_gui.x_fsf.x_put_in2out) + my_numbox_bang(x); +} + +static void my_numbox_size(t_my_numbox *x, t_symbol *s, int ac, t_atom *av) +{ + int h, w; + + w = (int)atom_getfloatarg(0, ac, av); + if(w < MINDIGITS) + w = MINDIGITS; + x->x_numwidth = w; + if(ac > 1) + { + h = (int)atom_getfloatarg(1, ac, av); + if(h < IEM_GUI_MINSIZE) + h = IEM_GUI_MINSIZE; + x->x_gui.x_h = h * IEMGUI_ZOOM(x); + } + my_numbox_calc_fontwidth(x); + iemgui_size((void *)x, &x->x_gui); +} + +static void my_numbox_delta(t_my_numbox *x, t_symbol *s, int ac, t_atom *av) +{iemgui_delta((void *)x, &x->x_gui, s, ac, av);} + +static void my_numbox_pos(t_my_numbox *x, t_symbol *s, int ac, t_atom *av) +{iemgui_pos((void *)x, &x->x_gui, s, ac, av);} + +static void my_numbox_range(t_my_numbox *x, t_symbol *s, int ac, t_atom *av) +{ + if(my_numbox_check_minmax(x, (double)atom_getfloatarg(0, ac, av), + (double)atom_getfloatarg(1, ac, av))) + { + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + /*my_numbox_bang(x);*/ + } +} + +static void my_numbox_color(t_my_numbox *x, t_symbol *s, int ac, t_atom *av) +{iemgui_color((void *)x, &x->x_gui, s, ac, av);} + +static void my_numbox_send(t_my_numbox *x, t_symbol *s) +{iemgui_send(x, &x->x_gui, s);} + +static void my_numbox_receive(t_my_numbox *x, t_symbol *s) +{iemgui_receive(x, &x->x_gui, s);} + +static void my_numbox_label(t_my_numbox *x, t_symbol *s) +{iemgui_label((void *)x, &x->x_gui, s);} + +static void my_numbox_label_pos(t_my_numbox *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);} + +static void my_numbox_label_font(t_my_numbox *x, + t_symbol *s, int ac, t_atom *av) +{ + int f = (int)atom_getfloatarg(1, ac, av); + + if(f < 4) + f = 4; + x->x_gui.x_fontsize = f; + f = (int)atom_getfloatarg(0, ac, av); + if((f < 0) || (f > 2)) + f = 0; + x->x_gui.x_fsf.x_font_style = f; + my_numbox_calc_fontwidth(x); + iemgui_label_font((void *)x, &x->x_gui, s, ac, av); +} + +static void my_numbox_log(t_my_numbox *x) +{ + x->x_lin0_log1 = 1; + if(my_numbox_check_minmax(x, x->x_min, x->x_max)) + { + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + /*my_numbox_bang(x);*/ + } +} + +static void my_numbox_lin(t_my_numbox *x) +{ + x->x_lin0_log1 = 0; +} + +static void my_numbox_init(t_my_numbox *x, t_floatarg f) +{ + x->x_gui.x_isa.x_loadinit = (f == 0.0) ? 0 : 1; +} + +static void my_numbox_loadbang(t_my_numbox *x, t_floatarg action) +{ + if(action == LB_LOAD && x->x_gui.x_isa.x_loadinit) + { + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + my_numbox_bang(x); + } +} + +static void my_numbox_key(void *z, t_floatarg fkey) +{ + t_my_numbox *x = z; + char c = fkey; + char buf[3]; + buf[1] = 0; + + if(c == 0) + { + x->x_gui.x_fsf.x_change = 0; + clock_unset(x->x_clock_reset); + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + return; + } + if(((c >= '0') && (c <= '9')) || (c == '.') || (c == '-') || + (c == 'e') || (c == '+') || (c == 'E')) + { + if(strlen(x->x_buf) < (IEMGUI_MAX_NUM_LEN-2)) + { + buf[0] = c; + strcat(x->x_buf, buf); + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + } + } + else if((c == '\b') || (c == 127)) + { + int sl = (int)strlen(x->x_buf) - 1; + + if(sl < 0) + sl = 0; + x->x_buf[sl] = 0; + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + } + else if((c == '\n') || (c == 13)) + { + x->x_val = atof(x->x_buf); + x->x_buf[0] = 0; + x->x_gui.x_fsf.x_change = 0; + clock_unset(x->x_clock_reset); + my_numbox_clip(x); + my_numbox_bang(x); + sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update); + } + clock_delay(x->x_clock_reset, 3000); +} + +static void my_numbox_list(t_my_numbox *x, t_symbol *s, int ac, t_atom *av) +{ + if(!ac) { + my_numbox_bang(x); + } + else if(IS_A_FLOAT(av, 0)) + { + my_numbox_set(x, atom_getfloatarg(0, ac, av)); + my_numbox_bang(x); + } +} + +static void *my_numbox_new(t_symbol *s, int argc, t_atom *argv) +{ + t_my_numbox *x = (t_my_numbox *)pd_new(my_numbox_class); + int w = 5, h = 14; + int lilo = 0, f = 0, ldx = 0, ldy = -8; + int fs = 10; + int log_height = 256; + double min = -1.0e+37, max = 1.0e+37, v = 0.0; + char str[144]; + + x->x_gui.x_bcol = 0xFCFCFC; + x->x_gui.x_fcol = 0x00; + x->x_gui.x_lcol = 0x00; + + if((argc >= 17)&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1) + &&IS_A_FLOAT(argv,2)&&IS_A_FLOAT(argv,3) + &&IS_A_FLOAT(argv,4)&&IS_A_FLOAT(argv,5) + &&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6)) + &&(IS_A_SYMBOL(argv,7)||IS_A_FLOAT(argv,7)) + &&(IS_A_SYMBOL(argv,8)||IS_A_FLOAT(argv,8)) + &&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10) + &&IS_A_FLOAT(argv,11)&&IS_A_FLOAT(argv,12)&&IS_A_FLOAT(argv,16)) + { + w = (int)atom_getfloatarg(0, argc, argv); + h = (int)atom_getfloatarg(1, argc, argv); + min = (double)atom_getfloatarg(2, argc, argv); + max = (double)atom_getfloatarg(3, argc, argv); + lilo = (int)atom_getfloatarg(4, argc, argv); + iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(5, argc, argv)); + iemgui_new_getnames(&x->x_gui, 6, argv); + ldx = (int)atom_getfloatarg(9, argc, argv); + ldy = (int)atom_getfloatarg(10, argc, argv); + iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(11, argc, argv)); + fs = (int)atom_getfloatarg(12, argc, argv); + iemgui_all_loadcolors(&x->x_gui, argv+13, argv+14, argv+15); + v = atom_getfloatarg(16, argc, argv); + } + else iemgui_new_getnames(&x->x_gui, 6, 0); + if((argc == 18)&&IS_A_FLOAT(argv,17)) + { + log_height = (int)atom_getfloatarg(17, argc, argv); + } + x->x_gui.x_draw = (t_iemfunptr)my_numbox_draw; + x->x_gui.x_fsf.x_snd_able = 1; + x->x_gui.x_fsf.x_rcv_able = 1; + x->x_gui.x_glist = (t_glist *)canvas_getcurrent(); + if(x->x_gui.x_isa.x_loadinit) + x->x_val = v; + else + x->x_val = 0.0; + if(lilo != 0) lilo = 1; + x->x_lin0_log1 = lilo; + if(log_height < 10) + log_height = 10; + x->x_log_height = log_height; + if(!strcmp(x->x_gui.x_snd->s_name, "empty")) + x->x_gui.x_fsf.x_snd_able = 0; + if(!strcmp(x->x_gui.x_rcv->s_name, "empty")) + x->x_gui.x_fsf.x_rcv_able = 0; + if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica"); + else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times"); + else { x->x_gui.x_fsf.x_font_style = 0; + strcpy(x->x_gui.x_font, sys_font); } + if(x->x_gui.x_fsf.x_rcv_able) + pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + x->x_gui.x_ldx = ldx; + x->x_gui.x_ldy = ldy; + if(fs < MINFONT) + fs = MINFONT; + x->x_gui.x_fontsize = fs; + if(w < MINDIGITS) + w = MINDIGITS; + x->x_numwidth = w; + if(h < IEM_GUI_MINSIZE) + h = IEM_GUI_MINSIZE; + x->x_gui.x_h = h; + x->x_buf[0] = 0; + my_numbox_check_minmax(x, min, max); + iemgui_verify_snd_ne_rcv(&x->x_gui); + x->x_clock_reset = clock_new(x, (t_method)my_numbox_tick_reset); + x->x_clock_wait = clock_new(x, (t_method)my_numbox_tick_wait); + x->x_gui.x_fsf.x_change = 0; + iemgui_newzoom(&x->x_gui); + my_numbox_calc_fontwidth(x); + outlet_new(&x->x_gui.x_obj, &s_float); + return (x); +} + +static void my_numbox_free(t_my_numbox *x) +{ + if(x->x_gui.x_fsf.x_rcv_able) + pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + clock_free(x->x_clock_reset); + clock_free(x->x_clock_wait); + gfxstub_deleteforkey(x); +} + +void g_numbox_setup(void) +{ + my_numbox_class = class_new(gensym("nbx"), (t_newmethod)my_numbox_new, + (t_method)my_numbox_free, sizeof(t_my_numbox), 0, A_GIMME, 0); + class_addcreator((t_newmethod)my_numbox_new, gensym("my_numbox"), A_GIMME, 0); + class_addbang(my_numbox_class, my_numbox_bang); + class_addfloat(my_numbox_class, my_numbox_float); + class_addlist(my_numbox_class, my_numbox_list); + class_addmethod(my_numbox_class, (t_method)my_numbox_click, + gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_motion, + gensym("motion"), A_FLOAT, A_FLOAT, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_dialog, + gensym("dialog"), A_GIMME, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_loadbang, + gensym("loadbang"), A_DEFFLOAT, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_set, + gensym("set"), A_FLOAT, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_size, + gensym("size"), A_GIMME, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_delta, + gensym("delta"), A_GIMME, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_pos, + gensym("pos"), A_GIMME, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_range, + gensym("range"), A_GIMME, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_color, + gensym("color"), A_GIMME, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_send, + gensym("send"), A_DEFSYM, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_receive, + gensym("receive"), A_DEFSYM, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_label, + gensym("label"), A_DEFSYM, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_label_pos, + gensym("label_pos"), A_GIMME, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_label_font, + gensym("label_font"), A_GIMME, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_log, + gensym("log"), 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_lin, + gensym("lin"), 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_init, + gensym("init"), A_FLOAT, 0); + class_addmethod(my_numbox_class, (t_method)my_numbox_log_height, + gensym("log_height"), A_FLOAT, 0); + class_addmethod(my_numbox_class, (t_method)iemgui_zoom, + gensym("zoom"), A_CANT, 0); + my_numbox_widgetbehavior.w_getrectfn = my_numbox_getrect; + my_numbox_widgetbehavior.w_displacefn = iemgui_displace; + my_numbox_widgetbehavior.w_selectfn = iemgui_select; + my_numbox_widgetbehavior.w_activatefn = NULL; + my_numbox_widgetbehavior.w_deletefn = iemgui_delete; + my_numbox_widgetbehavior.w_visfn = iemgui_vis; + my_numbox_widgetbehavior.w_clickfn = my_numbox_newclick; + class_setwidget(my_numbox_class, &my_numbox_widgetbehavior); + class_sethelpsymbol(my_numbox_class, gensym("numbox2")); + class_setsavefn(my_numbox_class, my_numbox_save); + class_setpropertiesfn(my_numbox_class, my_numbox_properties); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_readwrite.c b/ports/camomile/source/LibPd/pure-data/src/g_readwrite.c new file mode 100644 index 00000000..b94000ae --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_readwrite.c @@ -0,0 +1,811 @@ +/* Copyright (c) 1997-2002 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* +Routines to read and write canvases to files: +canvas_savetofile() writes a root canvas to a "pd" file. (Reading "pd" files +is done simply by passing the contents to the pd message interpreter.) +Alternatively, the glist_read() and glist_write() routines read and write +"data" from and to files (reading reads into an existing canvas), using a +file format as in the dialog window for data. +*/ + +#include +#include +#include "m_pd.h" +#include "g_canvas.h" +#include + +static t_class *declare_class; +void canvas_savedeclarationsto(t_canvas *x, t_binbuf *b); + + /* the following routines read "scalars" from a file into a canvas. */ + +static int canvas_scanbinbuf(int natoms, t_atom *vec, int *p_indexout, + int *p_next) +{ + int i, j; + int indexwas = *p_next; + *p_indexout = indexwas; + if (indexwas >= natoms) + return (0); + for (i = indexwas; i < natoms && vec[i].a_type != A_SEMI; i++) + ; + if (i >= natoms) + *p_next = i; + else *p_next = i + 1; + return (i - indexwas); +} + +int canvas_readscalar(t_glist *x, int natoms, t_atom *vec, + int *p_nextmsg, int selectit); + +static void canvas_readerror(int natoms, t_atom *vec, int message, + int nline, char *s) +{ + error("%s", s); + startpost("line was:"); + postatom(nline, vec + message); + endpost(); +} + + /* fill in the contents of the scalar into the vector w. */ + +static void glist_readatoms(t_glist *x, int natoms, t_atom *vec, + int *p_nextmsg, t_symbol *templatesym, t_word *w, int argc, t_atom *argv) +{ + int message, nline, n, i; + + t_template *template = template_findbyname(templatesym); + if (!template) + { + error("%s: no such template", templatesym->s_name); + *p_nextmsg = natoms; + return; + } + word_restore(w, template, argc, argv); + n = template->t_n; + for (i = 0; i < n; i++) + { + if (template->t_vec[i].ds_type == DT_ARRAY) + { + int j; + t_array *a = w[i].w_array; + int elemsize = a->a_elemsize, nitems = 0; + t_symbol *arraytemplatesym = template->t_vec[i].ds_arraytemplate; + t_template *arraytemplate = + template_findbyname(arraytemplatesym); + if (!arraytemplate) + { + error("%s: no such template", arraytemplatesym->s_name); + } + else while (1) + { + t_word *element; + int nline = canvas_scanbinbuf(natoms, vec, &message, p_nextmsg); + /* empty line terminates array */ + if (!nline) + break; + array_resize(a, nitems + 1); + element = (t_word *)(((char *)a->a_vec) + + nitems * elemsize); + glist_readatoms(x, natoms, vec, p_nextmsg, arraytemplatesym, + element, nline, vec + message); + nitems++; + } + } + else if (template->t_vec[i].ds_type == DT_TEXT) + { + t_binbuf *z = binbuf_new(); + int first = *p_nextmsg, last; + for (last = first; last < natoms && vec[last].a_type != A_SEMI; + last++); + binbuf_restore(z, last-first, vec+first); + binbuf_add(w[i].w_binbuf, binbuf_getnatom(z), binbuf_getvec(z)); + binbuf_free(z); + last++; + if (last > natoms) last = natoms; + *p_nextmsg = last; + } + } +} + +int canvas_readscalar(t_glist *x, int natoms, t_atom *vec, + int *p_nextmsg, int selectit) +{ + int message, i, j, nline; + t_template *template; + t_symbol *templatesym; + t_scalar *sc; + int nextmsg = *p_nextmsg; + int wasvis = glist_isvisible(x); + + if (nextmsg >= natoms || vec[nextmsg].a_type != A_SYMBOL) + { + if (nextmsg < natoms) + post("stopping early: type %d", vec[nextmsg].a_type); + *p_nextmsg = natoms; + return (0); + } + templatesym = canvas_makebindsym(vec[nextmsg].a_w.w_symbol); + *p_nextmsg = nextmsg + 1; + + if (!(template = template_findbyname(templatesym))) + { + error("canvas_read: %s: no such template", templatesym->s_name); + *p_nextmsg = natoms; + return (0); + } + sc = scalar_new(x, templatesym); + if (!sc) + { + error("couldn't create scalar \"%s\"", templatesym->s_name); + *p_nextmsg = natoms; + return (0); + } + if (wasvis) + { + /* temporarily lie about vis flag while this is built */ + glist_getcanvas(x)->gl_mapped = 0; + } + glist_add(x, &sc->sc_gobj); + + nline = canvas_scanbinbuf(natoms, vec, &message, p_nextmsg); + glist_readatoms(x, natoms, vec, p_nextmsg, templatesym, sc->sc_vec, + nline, vec + message); + if (wasvis) + { + /* reset vis flag as before */ + glist_getcanvas(x)->gl_mapped = 1; + gobj_vis(&sc->sc_gobj, x, 1); + } + if (selectit) + { + glist_select(x, &sc->sc_gobj); + } + return (1); +} + +void glist_readfrombinbuf(t_glist *x, t_binbuf *b, char *filename, int selectem) +{ + t_canvas *canvas = glist_getcanvas(x); + int cr = 0, natoms, nline, message, nextmsg = 0, i, j, nitems; + t_atom *vec; + t_gobj *gobj; + + natoms = binbuf_getnatom(b); + vec = binbuf_getvec(b); + + + /* check for file type */ + nline = canvas_scanbinbuf(natoms, vec, &message, &nextmsg); + if (nline != 1 && vec[message].a_type != A_SYMBOL && + strcmp(vec[message].a_w.w_symbol->s_name, "data")) + { + pd_error(x, "%s: file apparently of wrong type", filename); + return; + } + /* read in templates and check for consistency */ + while (1) + { + t_template *newtemplate, *existtemplate; + t_symbol *templatesym; + t_atom *templateargs = getbytes(0); + int ntemplateargs = 0, newnargs; + nline = canvas_scanbinbuf(natoms, vec, &message, &nextmsg); + if (nline < 2) + { + t_freebytes(templateargs, sizeof (*templateargs) * ntemplateargs); + break; + } + else if (nline > 2) + canvas_readerror(natoms, vec, message, nline, + "extra items ignored"); + else if (vec[message].a_type != A_SYMBOL || + strcmp(vec[message].a_w.w_symbol->s_name, "template") || + vec[message + 1].a_type != A_SYMBOL) + { + canvas_readerror(natoms, vec, message, nline, + "bad template header"); + continue; + } + templatesym = canvas_makebindsym(vec[message + 1].a_w.w_symbol); + while (1) + { + nline = canvas_scanbinbuf(natoms, vec, &message, &nextmsg); + if (nline != 2 && nline != 3) + break; + newnargs = ntemplateargs + nline; + templateargs = (t_atom *)t_resizebytes(templateargs, + sizeof(*templateargs) * ntemplateargs, + sizeof(*templateargs) * newnargs); + templateargs[ntemplateargs] = vec[message]; + templateargs[ntemplateargs + 1] = vec[message + 1]; + if (nline == 3) + templateargs[ntemplateargs + 2] = vec[message + 2]; + ntemplateargs = newnargs; + } + if (!(existtemplate = template_findbyname(templatesym))) + { + error("%s: template not found in current patch", + templatesym->s_name); + t_freebytes(templateargs, sizeof (*templateargs) * ntemplateargs); + return; + } + newtemplate = template_new(templatesym, ntemplateargs, templateargs); + t_freebytes(templateargs, sizeof (*templateargs) * ntemplateargs); + if (!template_match(existtemplate, newtemplate)) + { + error("%s: template doesn't match current one", + templatesym->s_name); + pd_free(&newtemplate->t_pdobj); + return; + } + pd_free(&newtemplate->t_pdobj); + } + while (nextmsg < natoms) + { + canvas_readscalar(x, natoms, vec, &nextmsg, selectem); + } +} + +static void glist_doread(t_glist *x, t_symbol *filename, t_symbol *format, + int clearme) +{ + t_binbuf *b = binbuf_new(); + t_canvas *canvas = glist_getcanvas(x); + int wasvis = glist_isvisible(canvas); + int cr = 0, natoms, nline, message, nextmsg = 0, i, j; + t_atom *vec; + + if (!strcmp(format->s_name, "cr")) + cr = 1; + else if (*format->s_name) + error("qlist_read: unknown flag: %s", format->s_name); + + if (binbuf_read_via_canvas(b, filename->s_name, canvas, cr)) + { + pd_error(x, "read failed"); + binbuf_free(b); + return; + } + if (wasvis) + canvas_vis(canvas, 0); + if (clearme) + glist_clear(x); + glist_readfrombinbuf(x, b, filename->s_name, 0); + if (wasvis) + canvas_vis(canvas, 1); + binbuf_free(b); +} + +void glist_read(t_glist *x, t_symbol *filename, t_symbol *format) +{ + glist_doread(x, filename, format, 1); +} + +void glist_mergefile(t_glist *x, t_symbol *filename, t_symbol *format) +{ + glist_doread(x, filename, format, 0); +} + + /* read text from a "properties" window, called from a gfxstub set + up in scalar_properties(). We try to restore the object; if successful + we either copy the data from the new scalar to the old one in place + (if their templates match) or else delete the old scalar and put the new + thing in its place on the list. */ +void canvas_dataproperties(t_canvas *x, t_scalar *sc, t_binbuf *b) +{ + int ntotal, nnew, scindex; + t_gobj *y, *y2 = 0, *newone, *oldone = 0; + t_template *template; + glist_noselect(x); + for (y = x->gl_list, ntotal = 0, scindex = -1; y; y = y->g_next) + { + if (y == &sc->sc_gobj) + scindex = ntotal, oldone = y; + ntotal++; + } + + if (scindex == -1) + { + error("data_properties: scalar disappeared"); + return; + } + glist_readfrombinbuf(x, b, "properties dialog", 0); + newone = 0; + /* take the new object off the list */ + if (ntotal) + { + for (y = x->gl_list, nnew = 1; (y2 = y->g_next); + y = y2, nnew++) + if (nnew == ntotal) + { + newone = y2; + gobj_vis(newone, x, 0); + y->g_next = y2->g_next; + break; + } + } + else gobj_vis((newone = x->gl_list), x, 0), x->gl_list = newone->g_next; + if (!newone) + error("couldn't update properties (perhaps a format problem?)"); + else if (!oldone) + bug("data_properties: couldn't find old element"); + else if (newone->g_pd == scalar_class && oldone->g_pd == scalar_class + && ((t_scalar *)newone)->sc_template == + ((t_scalar *)oldone)->sc_template + && (template = template_findbyname(((t_scalar *)newone)->sc_template))) + { + /* swap new one with old one; then delete new one */ + int i; + for (i = 0; i < template->t_n; i++) + { + t_word w = ((t_scalar *)newone)->sc_vec[i]; + ((t_scalar *)newone)->sc_vec[i] = ((t_scalar *)oldone)->sc_vec[i]; + ((t_scalar *)oldone)->sc_vec[i] = w; + } + pd_free(&newone->g_pd); + if (glist_isvisible(x)) + { + gobj_vis(oldone, x, 0); + gobj_vis(oldone, x, 1); + } + } + else + { + /* delete old one; put new one where the old one was on glist */ + glist_delete(x, oldone); + if (scindex > 0) + { + for (y = x->gl_list, nnew = 1; y; + y = y->g_next, nnew++) + if (nnew == scindex || !y->g_next) + { + newone->g_next = y->g_next; + y->g_next = newone; + goto didit; + } + bug("data_properties: can't reinsert"); + } + else newone->g_next = x->gl_list, x->gl_list = newone; + } +didit: + ; +} + + /* ----------- routines to write data to a binbuf ----------- */ + +void canvas_doaddtemplate(t_symbol *templatesym, + int *p_ntemplates, t_symbol ***p_templatevec) +{ + int n = *p_ntemplates, i; + t_symbol **templatevec = *p_templatevec; + for (i = 0; i < n; i++) + if (templatevec[i] == templatesym) + return; + templatevec = (t_symbol **)t_resizebytes(templatevec, + n * sizeof(*templatevec), (n+1) * sizeof(*templatevec)); + templatevec[n] = templatesym; + *p_templatevec = templatevec; + *p_ntemplates = n+1; +} + +static void glist_writelist(t_gobj *y, t_binbuf *b); + +void binbuf_savetext(t_binbuf *bfrom, t_binbuf *bto); + +void canvas_writescalar(t_symbol *templatesym, t_word *w, t_binbuf *b, + int amarrayelement) +{ + t_dataslot *ds; + t_template *template = template_findbyname(templatesym); + t_atom *a = (t_atom *)t_getbytes(0); + int i, n = template?(template->t_n):0, natom = 0; + if (!amarrayelement) + { + t_atom templatename; + SETSYMBOL(&templatename, gensym(templatesym->s_name + 3)); + binbuf_add(b, 1, &templatename); + } + if (!template) + bug("canvas_writescalar"); + /* write the atoms (floats and symbols) */ + for (i = 0; i < n; i++) + { + if (template->t_vec[i].ds_type == DT_FLOAT || + template->t_vec[i].ds_type == DT_SYMBOL) + { + a = (t_atom *)t_resizebytes(a, + natom * sizeof(*a), (natom + 1) * sizeof (*a)); + if (template->t_vec[i].ds_type == DT_FLOAT) + SETFLOAT(a + natom, w[i].w_float); + else SETSYMBOL(a + natom, w[i].w_symbol); + natom++; + } + } + /* array elements have to have at least something */ + if (natom == 0 && amarrayelement) + SETSYMBOL(a + natom, &s_bang), natom++; + binbuf_add(b, natom, a); + binbuf_addsemi(b); + t_freebytes(a, natom * sizeof(*a)); + for (i = 0; i < n; i++) + { + if (template->t_vec[i].ds_type == DT_ARRAY) + { + int j; + t_array *a = w[i].w_array; + int elemsize = a->a_elemsize, nitems = a->a_n; + t_symbol *arraytemplatesym = template->t_vec[i].ds_arraytemplate; + for (j = 0; j < nitems; j++) + canvas_writescalar(arraytemplatesym, + (t_word *)(((char *)a->a_vec) + elemsize * j), b, 1); + binbuf_addsemi(b); + } + else if (template->t_vec[i].ds_type == DT_TEXT) + binbuf_savetext(w[i].w_binbuf, b); + } +} + +static void glist_writelist(t_gobj *y, t_binbuf *b) +{ + for (; y; y = y->g_next) + { + if (pd_class(&y->g_pd) == scalar_class) + { + canvas_writescalar(((t_scalar *)y)->sc_template, + ((t_scalar *)y)->sc_vec, b, 0); + } + } +} + + /* ------------ routines to write out templates for data ------- */ + +static void canvas_addtemplatesforlist(t_gobj *y, + int *p_ntemplates, t_symbol ***p_templatevec); + +static void canvas_addtemplatesforscalar(t_symbol *templatesym, + t_word *w, int *p_ntemplates, t_symbol ***p_templatevec) +{ + t_dataslot *ds; + int i; + t_template *template = template_findbyname(templatesym); + canvas_doaddtemplate(templatesym, p_ntemplates, p_templatevec); + if (!template) + bug("canvas_addtemplatesforscalar"); + else for (ds = template->t_vec, i = template->t_n; i--; ds++, w++) + { + if (ds->ds_type == DT_ARRAY) + { + int j; + t_array *a = w->w_array; + int elemsize = a->a_elemsize, nitems = a->a_n; + t_symbol *arraytemplatesym = ds->ds_arraytemplate; + canvas_doaddtemplate(arraytemplatesym, p_ntemplates, p_templatevec); + for (j = 0; j < nitems; j++) + canvas_addtemplatesforscalar(arraytemplatesym, + (t_word *)(((char *)a->a_vec) + elemsize * j), + p_ntemplates, p_templatevec); + } + } +} + +static void canvas_addtemplatesforlist(t_gobj *y, + int *p_ntemplates, t_symbol ***p_templatevec) +{ + for (; y; y = y->g_next) + { + if (pd_class(&y->g_pd) == scalar_class) + { + canvas_addtemplatesforscalar(((t_scalar *)y)->sc_template, + ((t_scalar *)y)->sc_vec, p_ntemplates, p_templatevec); + } + } +} + + /* write all "scalars" in a glist to a binbuf. */ +t_binbuf *glist_writetobinbuf(t_glist *x, int wholething) +{ + int i; + t_symbol **templatevec = getbytes(0); + int ntemplates = 0; + t_gobj *y; + t_binbuf *b = binbuf_new(); + + for (y = x->gl_list; y; y = y->g_next) + { + if ((pd_class(&y->g_pd) == scalar_class) && + (wholething || glist_isselected(x, y))) + { + canvas_addtemplatesforscalar(((t_scalar *)y)->sc_template, + ((t_scalar *)y)->sc_vec, &ntemplates, &templatevec); + } + } + binbuf_addv(b, "s;", gensym("data")); + for (i = 0; i < ntemplates; i++) + { + t_template *template = template_findbyname(templatevec[i]); + int j, m = template->t_n; + /* drop "pd-" prefix from template symbol to print it: */ + binbuf_addv(b, "ss;", gensym("template"), + gensym(templatevec[i]->s_name + 3)); + for (j = 0; j < m; j++) + { + t_symbol *type; + switch (template->t_vec[j].ds_type) + { + case DT_FLOAT: type = &s_float; break; + case DT_SYMBOL: type = &s_symbol; break; + case DT_ARRAY: type = gensym("array"); break; + case DT_TEXT: type = &s_list; break; + default: type = &s_float; bug("canvas_write"); + } + if (template->t_vec[j].ds_type == DT_ARRAY) + binbuf_addv(b, "sss;", type, template->t_vec[j].ds_name, + gensym(template->t_vec[j].ds_arraytemplate->s_name + 3)); + else binbuf_addv(b, "ss;", type, template->t_vec[j].ds_name); + } + binbuf_addsemi(b); + } + binbuf_addsemi(b); + /* now write out the objects themselves */ + for (y = x->gl_list; y; y = y->g_next) + { + if ((pd_class(&y->g_pd) == scalar_class) && + (wholething || glist_isselected(x, y))) + { + canvas_writescalar(((t_scalar *)y)->sc_template, + ((t_scalar *)y)->sc_vec, b, 0); + } + } + t_freebytes(templatevec, ntemplates*sizeof(*templatevec)); + return (b); +} + +static void glist_write(t_glist *x, t_symbol *filename, t_symbol *format) +{ + int cr = 0, i; + t_binbuf *b; + char buf[MAXPDSTRING]; + t_gobj *y; + t_canvas *canvas = glist_getcanvas(x); + canvas_makefilename(canvas, filename->s_name, buf, MAXPDSTRING); + if (!strcmp(format->s_name, "cr")) + cr = 1; + else if (*format->s_name) + error("qlist_read: unknown flag: %s", format->s_name); + + b = glist_writetobinbuf(x, 1); + if (b) + { + if (binbuf_write(b, buf, "", cr)) + error("%s: write failed", filename->s_name); + binbuf_free(b); + } +} + +/* ------ routines to save and restore canvases (patches) recursively. ----*/ + +typedef void (*t_zoomfn)(void *x, t_floatarg arg1); + + /* save to a binbuf, called recursively; cf. canvas_savetofile() which + saves the document, and is only called on root canvases. */ +static void canvas_saveto(t_canvas *x, t_binbuf *b) +{ + t_gobj *y; + t_linetraverser t; + t_outconnect *oc; + int zoomwas = x->gl_zoom; + + if (zoomwas > 1) + { + t_zoomfn zoommethod = (t_zoomfn)zgetfn(&x->gl_pd, gensym("zoom")); + if (zoommethod) + (*zoommethod)(&x->gl_pd, (t_floatarg)1); + } + /* subpatch */ + if (x->gl_owner && !x->gl_env) + { + /* have to go to original binbuf to find out how we were named. */ + t_binbuf *bz = binbuf_new(); + t_symbol *patchsym; + binbuf_addbinbuf(bz, x->gl_obj.ob_binbuf); + patchsym = atom_getsymbolarg(1, binbuf_getnatom(bz), binbuf_getvec(bz)); + binbuf_free(bz); + binbuf_addv(b, "ssiiiisi;", gensym("#N"), gensym("canvas"), + (int)(x->gl_screenx1), + (int)(x->gl_screeny1), + (int)(x->gl_screenx2 - x->gl_screenx1), + (int)(x->gl_screeny2 - x->gl_screeny1), + (patchsym != &s_ ? patchsym: gensym("(subpatch)")), + x->gl_mapped); + } + /* root or abstraction */ + else + { + binbuf_addv(b, "ssiiiii;", gensym("#N"), gensym("canvas"), + (int)(x->gl_screenx1), + (int)(x->gl_screeny1), + (int)(x->gl_screenx2 - x->gl_screenx1), + (int)(x->gl_screeny2 - x->gl_screeny1), + (int)x->gl_font); + canvas_savedeclarationsto(x, b); + } + for (y = x->gl_list; y; y = y->g_next) + gobj_save(y, b); + + linetraverser_start(&t, x); + while ((oc = linetraverser_next(&t))) + { + int srcno = canvas_getindex(x, &t.tr_ob->ob_g); + int sinkno = canvas_getindex(x, &t.tr_ob2->ob_g); + binbuf_addv(b, "ssiiii;", gensym("#X"), gensym("connect"), + srcno, t.tr_outno, sinkno, t.tr_inno); + } + /* unless everything is the default (as in ordinary subpatches) + print out a "coords" message to set up the coordinate systems */ + if (x->gl_isgraph || x->gl_x1 || x->gl_y1 || + x->gl_x2 != 1 || x->gl_y2 != 1 || x->gl_pixwidth || x->gl_pixheight) + { + if (x->gl_isgraph && x->gl_goprect) + /* if we have a graph-on-parent rectangle, we're new style. + The format is arranged so + that old versions of Pd can at least do something with it. */ + binbuf_addv(b, "ssfffffffff;", gensym("#X"), gensym("coords"), + x->gl_x1, x->gl_y1, + x->gl_x2, x->gl_y2, + (t_float)x->gl_pixwidth, (t_float)x->gl_pixheight, + (t_float)((x->gl_hidetext)?2.:1.), + (t_float)x->gl_xmargin, (t_float)x->gl_ymargin); + /* otherwise write in 0.38-compatible form */ + else binbuf_addv(b, "ssfffffff;", gensym("#X"), gensym("coords"), + x->gl_x1, x->gl_y1, + x->gl_x2, x->gl_y2, + (t_float)x->gl_pixwidth, (t_float)x->gl_pixheight, + (t_float)x->gl_isgraph); + } + if (zoomwas > 1) + { + t_zoomfn zoommethod = (t_zoomfn)zgetfn(&x->gl_pd, gensym("zoom")); + if (zoommethod) + (*zoommethod)(&x->gl_pd, (t_floatarg)zoomwas); + } +} + + /* call this recursively to collect all the template names for + a canvas or for the selection. */ +static void canvas_collecttemplatesfor(t_canvas *x, int *ntemplatesp, + t_symbol ***templatevecp, int wholething) +{ + t_gobj *y; + + for (y = x->gl_list; y; y = y->g_next) + { + if ((pd_class(&y->g_pd) == scalar_class) && + (wholething || glist_isselected(x, y))) + canvas_addtemplatesforscalar(((t_scalar *)y)->sc_template, + ((t_scalar *)y)->sc_vec, ntemplatesp, templatevecp); + else if ((pd_class(&y->g_pd) == canvas_class) && + (wholething || glist_isselected(x, y))) + canvas_collecttemplatesfor((t_canvas *)y, + ntemplatesp, templatevecp, 1); + } +} + + /* save the templates needed by a canvas to a binbuf. */ +static void canvas_savetemplatesto(t_canvas *x, t_binbuf *b, int wholething) +{ + t_symbol **templatevec = getbytes(0); + int i, ntemplates = 0; + t_gobj *y; + canvas_collecttemplatesfor(x, &ntemplates, &templatevec, wholething); + for (i = 0; i < ntemplates; i++) + { + t_template *template = template_findbyname(templatevec[i]); + int j, m; + if (!template) + { + bug("canvas_savetemplatesto"); + continue; + } + m = template->t_n; + /* drop "pd-" prefix from template symbol to print */ + binbuf_addv(b, "sss", &s__N, gensym("struct"), + gensym(templatevec[i]->s_name + 3)); + for (j = 0; j < m; j++) + { + t_symbol *type; + switch (template->t_vec[j].ds_type) + { + case DT_FLOAT: type = &s_float; break; + case DT_SYMBOL: type = &s_symbol; break; + case DT_ARRAY: type = gensym("array"); break; + case DT_TEXT: type = gensym("text"); break; + default: type = &s_float; bug("canvas_write"); + } + if (template->t_vec[j].ds_type == DT_ARRAY) + binbuf_addv(b, "sss", type, template->t_vec[j].ds_name, + gensym(template->t_vec[j].ds_arraytemplate->s_name + 3)); + else binbuf_addv(b, "ss", type, template->t_vec[j].ds_name); + } + binbuf_addsemi(b); + } +} + +void canvas_reload(t_symbol *name, t_symbol *dir, t_glist *except); + + /* save a "root" canvas to a file; cf. canvas_saveto() which saves the + body (and which is called recursively.) */ +static void canvas_savetofile(t_canvas *x, t_symbol *filename, t_symbol *dir, + float fdestroy) +{ + t_binbuf *b = binbuf_new(); + canvas_savetemplatesto(x, b, 1); + canvas_saveto(x, b); + if (binbuf_write(b, filename->s_name, dir->s_name, 0)) sys_ouch(); + else + { + /* if not an abstraction, reset title bar and directory */ + if (!x->gl_owner) +{ + canvas_rename(x, filename, dir); + /* update window list in case Save As changed the window name */ + canvas_updatewindowlist(); +} + post("saved to: %s/%s", dir->s_name, filename->s_name); + canvas_dirty(x, 0); + canvas_reload(filename, dir, x); + if (fdestroy != 0) + vmess(&x->gl_pd, gensym("menuclose"), "f", 1.); + } + binbuf_free(b); +} + +static void canvas_menusaveas(t_canvas *x, float fdestroy) +{ + t_canvas *x2 = canvas_getrootfor(x); + sys_vgui("pdtk_canvas_saveas .x%lx {%s} {%s} %d\n", x2, + x2->gl_name->s_name, canvas_getdir(x2)->s_name, (fdestroy != 0)); +} + +static void canvas_menusave(t_canvas *x, float fdestroy) +{ + t_canvas *x2 = canvas_getrootfor(x); + char *name = x2->gl_name->s_name; + if (*name && strncmp(name, "Untitled", 8) + && (strlen(name) < 4 || strcmp(name + strlen(name)-4, ".pat") + || strcmp(name + strlen(name)-4, ".mxt"))) + { + canvas_savetofile(x2, x2->gl_name, canvas_getdir(x2), fdestroy); + } + else canvas_menusaveas(x2, fdestroy); +} + +void g_readwrite_setup(void) +{ + class_addmethod(canvas_class, (t_method)glist_write, + gensym("write"), A_SYMBOL, A_DEFSYM, A_NULL); + class_addmethod(canvas_class, (t_method)glist_read, + gensym("read"), A_SYMBOL, A_DEFSYM, A_NULL); + class_addmethod(canvas_class, (t_method)glist_mergefile, + gensym("mergefile"), A_SYMBOL, A_DEFSYM, A_NULL); + class_addmethod(canvas_class, (t_method)canvas_savetofile, + gensym("savetofile"), A_SYMBOL, A_SYMBOL, A_DEFFLOAT, 0); + class_addmethod(canvas_class, (t_method)canvas_saveto, + gensym("saveto"), A_CANT, 0); +/* ------------------ from the menu ------------------------- */ + class_addmethod(canvas_class, (t_method)canvas_menusave, + gensym("menusave"), A_DEFFLOAT, 0); + class_addmethod(canvas_class, (t_method)canvas_menusaveas, + gensym("menusaveas"), A_DEFFLOAT, 0); +} + +void canvas_readwrite_for_class(t_class *c) +{ + class_addmethod(c, (t_method)canvas_menusave, + gensym("menusave"), A_DEFFLOAT, 0); + class_addmethod(c, (t_method)canvas_menusaveas, + gensym("menusaveas"), A_DEFFLOAT, 0); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_rtext.c b/ports/camomile/source/LibPd/pure-data/src/g_rtext.c new file mode 100644 index 00000000..0acbf71d --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_rtext.c @@ -0,0 +1,664 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* changes by Thomas Musil IEM KUG Graz Austria 2001 */ +/* have to insert gui-objects into editor-list */ +/* all changes are labeled with iemlib */ + +#include +#include +#include +#include +#include "m_pd.h" +#include "s_stuff.h" +#include "g_canvas.h" +#include "s_utf8.h" + +#define LMARGIN 2 +#define RMARGIN 2 +#define TMARGIN 3 +#define BMARGIN 2 + +#define SEND_FIRST 1 +#define SEND_UPDATE 2 +#define SEND_CHECK 0 + +struct _rtext +{ + char *x_buf; /*-- raw byte string, assumed UTF-8 encoded (moo) --*/ + int x_bufsize; /*-- byte length --*/ + int x_selstart; /*-- byte offset --*/ + int x_selend; /*-- byte offset --*/ + int x_active; + int x_dragfrom; + int x_height; + int x_drawnwidth; + int x_drawnheight; + t_text *x_text; + t_glist *x_glist; + char x_tag[50]; + struct _rtext *x_next; +}; + +t_rtext *rtext_new(t_glist *glist, t_text *who) +{ + t_rtext *x = (t_rtext *)getbytes(sizeof *x); + int w = 0, h = 0, indx; + x->x_height = -1; + x->x_text = who; + x->x_glist = glist; + x->x_next = glist->gl_editor->e_rtext; + x->x_selstart = x->x_selend = x->x_active = + x->x_drawnwidth = x->x_drawnheight = 0; + binbuf_gettext(who->te_binbuf, &x->x_buf, &x->x_bufsize); + glist->gl_editor->e_rtext = x; + sprintf(x->x_tag, ".x%lx.t%lx", (t_int)glist_getcanvas(x->x_glist), + (t_int)x); + return (x); +} + +void rtext_free(t_rtext *x) +{ + if (x->x_glist->gl_editor->e_textedfor == x) + x->x_glist->gl_editor->e_textedfor = 0; + if (x->x_glist->gl_editor->e_rtext == x) + x->x_glist->gl_editor->e_rtext = x->x_next; + else + { + t_rtext *e2; + for (e2 = x->x_glist->gl_editor->e_rtext; e2; e2 = e2->x_next) + if (e2->x_next == x) + { + e2->x_next = x->x_next; + break; + } + } + freebytes(x->x_buf, x->x_bufsize); + freebytes(x, sizeof *x); +} + +char *rtext_gettag(t_rtext *x) +{ + return (x->x_tag); +} + +void rtext_gettext(t_rtext *x, char **buf, int *bufsize) +{ + *buf = x->x_buf; + *bufsize = x->x_bufsize; +} + +void rtext_getseltext(t_rtext *x, char **buf, int *bufsize) +{ + *buf = x->x_buf + x->x_selstart; + *bufsize = x->x_selend - x->x_selstart; +} + +/* convert t_text te_type symbol for use as a Tk tag */ +static t_symbol *rtext_gettype(t_rtext *x) +{ + switch (x->x_text->te_type) + { + case T_TEXT: return gensym("text"); + case T_OBJECT: return gensym("obj"); + case T_MESSAGE: return gensym("msg"); + case T_ATOM: return gensym("atom"); + } + return (&s_); +} + +/* LATER deal with tcl-significant characters */ + +/* firstone(), lastone() + * + returns byte offset of (first|last) occurrence of 'c' in 's[0..n-1]', or + * -1 if none was found + * + 's' is a raw byte string + * + 'c' is a byte value + * + 'n' is the length (in bytes) of the prefix of 's' to be searched. + * + we could make these functions work on logical characters in utf8 strings, + * but we don't really need to... + */ +static int firstone(char *s, int c, int n) +{ + char *s2 = s + n; + int i = 0; + while (s != s2) + { + if (*s == c) return (i); + i++; + s++; + } + return (-1); +} + +static int lastone(char *s, int c, int n) +{ + char *s2 = s + n; + while (s2 != s) + { + s2--; + n--; + if (*s2 == c) return (n); + } + return (-1); +} + + /* the following routine computes line breaks and carries out + some action which could be: + SEND_FIRST - draw the box for the first time + SEND_UPDATE - redraw the updated box + otherwise - don't draw, just calculate. + Called with *widthp and *heightp as coordinates of + a test point, the routine reports the index of the character found + there in *indexp. *widthp and *heightp are set to the width and height + of the entire text in pixels. + */ + + /*-- moo: + * + some variables from the original version have been renamed + * + variables with a "_b" suffix are raw byte strings, lengths, or offsets + * + variables with a "_c" suffix are logical character lengths or offsets + * (assuming valid UTF-8 encoded byte string in x->x_buf) + * + a fair amount of O(n) computations required to convert between raw byte + * offsets (needed by the C side) and logical character offsets (needed by + * the GUI) + */ + + /* LATER get this and sys_vgui to work together properly, + breaking up messages as needed. As of now, there's + a limit of 1950 characters, imposed by sys_vgui(). */ +#define UPBUFSIZE 4000 +#define BOXWIDTH 60 + +static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp, + int *indexp) +{ + t_float dispx, dispy; + char smallbuf[200], *tempbuf; + int outchars_b = 0, nlines = 0, ncolumns = 0, + pixwide, pixhigh, font, fontwidth, fontheight, findx, findy; + int reportedindex = 0; + t_canvas *canvas = glist_getcanvas(x->x_glist); + int widthspec_c = x->x_text->te_width; + int widthlimit_c = (widthspec_c ? widthspec_c : BOXWIDTH); + int inindex_b = 0; + int inindex_c = 0; + int selstart_b = 0, selend_b = 0; + int x_bufsize_c = u8_charnum(x->x_buf, x->x_bufsize); + /* if we're a GOP (the new, "goprect" style) borrow the font size + from the inside to preserve the spacing */ + if (pd_class(&x->x_text->te_pd) == canvas_class && + ((t_glist *)(x->x_text))->gl_isgraph && + ((t_glist *)(x->x_text))->gl_goprect) + { + font = glist_getfont((t_glist *)(x->x_text)); + fontwidth = glist_fontwidth((t_glist *)(x->x_text)); + fontheight = glist_fontheight((t_glist *)(x->x_text)); + } + else + { + font = glist_getfont(x->x_glist); + fontwidth = glist_fontwidth(x->x_glist); + fontheight = glist_fontheight(x->x_glist); + } + findx = (*widthp + (fontwidth/2)) / fontwidth; + findy = *heightp / fontheight; + if (x->x_bufsize >= 100) + tempbuf = (char *)t_getbytes(2 * x->x_bufsize + 1); + else tempbuf = smallbuf; + while (x_bufsize_c - inindex_c > 0) + { + int inchars_b = x->x_bufsize - inindex_b; + int inchars_c = x_bufsize_c - inindex_c; + int maxindex_c = (inchars_c > widthlimit_c ? widthlimit_c : inchars_c); + int maxindex_b = u8_offset(x->x_buf + inindex_b, maxindex_c); + int eatchar = 1; + int foundit_b = firstone(x->x_buf + inindex_b, '\n', maxindex_b); + int foundit_c; + if (foundit_b < 0) + { + /* too much text to fit in one line? */ + if (inchars_c > widthlimit_c) + { + /* is there a space to break the line at? OK if it's even + one byte past the end since in this context we know there's + more text */ + foundit_b = lastone(x->x_buf + inindex_b, ' ', maxindex_b + 1); + if (foundit_b < 0) + { + foundit_b = maxindex_b; + foundit_c = maxindex_c; + eatchar = 0; + } + else + foundit_c = u8_charnum(x->x_buf + inindex_b, foundit_b); + } + else + { + foundit_b = inchars_b; + foundit_c = inchars_c; + eatchar = 0; + } + } + else + foundit_c = u8_charnum(x->x_buf + inindex_b, foundit_b); + + if (nlines == findy) + { + int actualx = (findx < 0 ? 0 : + (findx > foundit_c ? foundit_c : findx)); + *indexp = inindex_b + u8_offset(x->x_buf + inindex_b, actualx); + reportedindex = 1; + } + strncpy(tempbuf+outchars_b, x->x_buf + inindex_b, foundit_b); + if (x->x_selstart >= inindex_b && + x->x_selstart <= inindex_b + foundit_b + eatchar) + selstart_b = x->x_selstart + outchars_b - inindex_b; + if (x->x_selend >= inindex_b && + x->x_selend <= inindex_b + foundit_b + eatchar) + selend_b = x->x_selend + outchars_b - inindex_b; + outchars_b += foundit_b; + inindex_b += (foundit_b + eatchar); + inindex_c += (foundit_c + eatchar); + if (inindex_b < x->x_bufsize) + tempbuf[outchars_b++] = '\n'; + if (foundit_c > ncolumns) + ncolumns = foundit_c; + nlines++; + } + if (!reportedindex) + *indexp = outchars_b; + dispx = text_xpix(x->x_text, x->x_glist); + dispy = text_ypix(x->x_text, x->x_glist); + if (nlines < 1) nlines = 1; + if (!widthspec_c) + { + while (ncolumns < (x->x_text->te_type == T_TEXT ? 1 : 3)) + { + tempbuf[outchars_b++] = ' '; + ncolumns++; + } + } + else ncolumns = widthspec_c; + pixwide = ncolumns * fontwidth; + pixhigh = nlines * fontheight; + if (glist_getzoom(x->x_glist) > 1) + { + /* zoom margins */ + pixwide += (LMARGIN + RMARGIN) * glist_getzoom(x->x_glist); + pixhigh += (TMARGIN + BMARGIN) * glist_getzoom(x->x_glist); + } + else + { + pixwide += LMARGIN + RMARGIN; + pixhigh += TMARGIN + BMARGIN; + } + + if (action && x->x_text->te_width && x->x_text->te_type != T_ATOM) + { + /* if our width is specified but the "natural" width is the + same as the specified width, set specified width to zero + so future text editing will automatically change width. + Except atoms whose content changes at runtime. */ + int widthwas = x->x_text->te_width, newwidth = 0, newheight = 0, + newindex = 0; + x->x_text->te_width = 0; + rtext_senditup(x, 0, &newwidth, &newheight, &newindex); + if (newwidth/fontwidth != widthwas) + x->x_text->te_width = widthwas; + else x->x_text->te_width = 0; + } + if (action == SEND_FIRST) + { + int lmargin = LMARGIN, tmargin = TMARGIN; + if (glist_getzoom(x->x_glist) > 1) + { + /* zoom margins */ + lmargin *= glist_getzoom(x->x_glist); + tmargin *= glist_getzoom(x->x_glist); + } + sys_vgui("pdtk_text_new .x%lx.c {%s %s text} %f %f {%.*s} %d %s\n", + canvas, x->x_tag, rtext_gettype(x)->s_name, + dispx + lmargin, dispy + tmargin, + outchars_b, tempbuf, + sys_hostfontsize(font, glist_getzoom(x->x_glist)), + (glist_isselected(x->x_glist, + &x->x_glist->gl_gobj)? "blue" : "black")); + } + else if (action == SEND_UPDATE) + { + sys_vgui("pdtk_text_set .x%lx.c %s {%.*s}\n", + canvas, x->x_tag, outchars_b, tempbuf); + if (pixwide != x->x_drawnwidth || pixhigh != x->x_drawnheight) + text_drawborder(x->x_text, x->x_glist, x->x_tag, + pixwide, pixhigh, 0); + if (x->x_active) + { + if (selend_b > selstart_b) + { + sys_vgui(".x%lx.c select from %s %d\n", canvas, + x->x_tag, u8_charnum(x->x_buf, selstart_b)); + sys_vgui(".x%lx.c select to %s %d\n", canvas, + x->x_tag, u8_charnum(x->x_buf, selend_b) - 1); + sys_vgui(".x%lx.c focus \"\"\n", canvas); + } + else + { + sys_vgui(".x%lx.c select clear\n", canvas); + sys_vgui(".x%lx.c icursor %s %d\n", canvas, x->x_tag, + u8_charnum(x->x_buf, selstart_b)); + sys_vgui(".x%lx.c focus %s\n", canvas, x->x_tag); + } + } + } + x->x_drawnwidth = pixwide; + x->x_drawnheight = pixhigh; + + *widthp = pixwide; + *heightp = pixhigh; + if (tempbuf != smallbuf) + t_freebytes(tempbuf, 2 * x->x_bufsize + 1); +} + +void rtext_retext(t_rtext *x) +{ + int w = 0, h = 0, indx; + t_text *text = x->x_text; + t_freebytes(x->x_buf, x->x_bufsize); + binbuf_gettext(text->te_binbuf, &x->x_buf, &x->x_bufsize); + /* special case: for number boxes, try to pare the number down + to the specified width of the box. */ + if (text->te_width > 0 && text->te_type == T_ATOM && + x->x_bufsize > text->te_width) + { + t_atom *atomp = binbuf_getvec(text->te_binbuf); + int natom = binbuf_getnatom(text->te_binbuf); + int bufsize = x->x_bufsize; + if (natom == 1 && atomp->a_type == A_FLOAT) + { + /* try to reduce size by dropping decimal digits */ + int wantreduce = bufsize - text->te_width; + char *decimal = 0, *nextchar, *ebuf = x->x_buf + bufsize, + *s1, *s2; + int ndecimals; + for (decimal = x->x_buf; decimal < ebuf; decimal++) + if (*decimal == '.') + break; + if (decimal >= ebuf) + goto giveup; + for (nextchar = decimal + 1; nextchar < ebuf; nextchar++) + if (*nextchar < '0' || *nextchar > '9') + break; + if (nextchar - decimal - 1 < wantreduce) + goto giveup; + for (s1 = nextchar - wantreduce, s2 = s1 + wantreduce; + s2 < ebuf; s1++, s2++) + *s1 = *s2; + x->x_buf = t_resizebytes(x->x_buf, bufsize, text->te_width); + bufsize = text->te_width; + goto done; + giveup: + /* give up and bash it to "+" or "-" */ + x->x_buf[0] = (atomp->a_w.w_float < 0 ? '-' : '+'); + x->x_buf = t_resizebytes(x->x_buf, bufsize, 1); + bufsize = 1; + } + else if (bufsize > text->te_width) + { + x->x_buf[text->te_width - 1] = '>'; + x->x_buf = t_resizebytes(x->x_buf, bufsize, text->te_width); + bufsize = text->te_width; + } + done: + x->x_bufsize = bufsize; + } + rtext_senditup(x, SEND_UPDATE, &w, &h, &indx); +} + +/* find the rtext that goes with a text item */ +t_rtext *glist_findrtext(t_glist *gl, t_text *who) +{ + t_rtext *x; + if (!gl->gl_editor) + canvas_create_editor(gl); + { + int i = 0; + for (x = gl->gl_editor->e_rtext; x && x->x_text != who; x = x->x_next) + i++; + // post("i=%d", i); + } + for (x = gl->gl_editor->e_rtext; x && x->x_text != who; x = x->x_next) + ; + return (x); +} + +int rtext_width(t_rtext *x) +{ + int w = 0, h = 0, indx; + rtext_senditup(x, SEND_CHECK, &w, &h, &indx); + return (w); +} + +int rtext_height(t_rtext *x) +{ + int w = 0, h = 0, indx; + rtext_senditup(x, SEND_CHECK, &w, &h, &indx); + return (h); +} + +void rtext_draw(t_rtext *x) +{ + int w = 0, h = 0, indx; + rtext_senditup(x, SEND_FIRST, &w, &h, &indx); +} + +void rtext_erase(t_rtext *x) +{ + sys_vgui(".x%lx.c delete %s\n", glist_getcanvas(x->x_glist), x->x_tag); +} + +void rtext_displace(t_rtext *x, int dx, int dy) +{ + sys_vgui(".x%lx.c move %s %d %d\n", glist_getcanvas(x->x_glist), + x->x_tag, dx, dy); +} + +void rtext_select(t_rtext *x, int state) +{ + t_glist *glist = x->x_glist; + t_canvas *canvas = glist_getcanvas(glist); + sys_vgui(".x%lx.c itemconfigure %s -fill %s\n", canvas, + x->x_tag, (state? "blue" : "black")); +} + +void rtext_activate(t_rtext *x, int state) +{ + int w = 0, h = 0, indx; + t_glist *glist = x->x_glist; + t_canvas *canvas = glist_getcanvas(glist); + if (state) + { + sys_vgui("pdtk_text_editing .x%lx %s 1\n", canvas, x->x_tag); + glist->gl_editor->e_textedfor = x; + glist->gl_editor->e_textdirty = 0; + x->x_dragfrom = x->x_selstart = 0; + x->x_selend = x->x_bufsize; + x->x_active = 1; + } + else + { + sys_vgui("pdtk_text_editing .x%lx {} 0\n", canvas); + if (glist->gl_editor->e_textedfor == x) + glist->gl_editor->e_textedfor = 0; + x->x_active = 0; + } + rtext_senditup(x, SEND_UPDATE, &w, &h, &indx); +} + +void rtext_key(t_rtext *x, int keynum, t_symbol *keysym) +{ + int w = 0, h = 0, indx, i, newsize, ndel; + char *s1, *s2; + if (keynum) + { + int n = keynum; + if (n == '\r') n = '\n'; + if (n == '\b') /* backspace */ + { + /* LATER delete the box if all text is selected... + this causes reentrancy problems now. */ + /* if ((!x->x_selstart) && (x->x_selend == x->x_bufsize)) + { + .... + } */ + if (x->x_selstart && (x->x_selstart == x->x_selend)) + u8_dec(x->x_buf, &x->x_selstart); + } + else if (n == 127) /* delete */ + { + if (x->x_selend < x->x_bufsize && (x->x_selstart == x->x_selend)) + u8_inc(x->x_buf, &x->x_selend); + } + + ndel = x->x_selend - x->x_selstart; + for (i = x->x_selend; i < x->x_bufsize; i++) + x->x_buf[i- ndel] = x->x_buf[i]; + newsize = x->x_bufsize - ndel; + x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize); + x->x_bufsize = newsize; + +/* at Guenter's suggestion, use 'n>31' to test wither a character might +be printable in whatever 8-bit character set we find ourselves. */ + +/*-- moo: + ... but test with "<" rather than "!=" in order to accommodate unicode + codepoints for n (which we get since Tk is sending the "%A" substitution + for bind ), effectively reducing the coverage of this clause to 7 + bits. Case n>127 is covered by the next clause. +*/ + if (n == '\n' || (n > 31 && n < 127)) + { + newsize = x->x_bufsize+1; + x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize); + for (i = x->x_bufsize; i > x->x_selstart; i--) + x->x_buf[i] = x->x_buf[i-1]; + x->x_buf[x->x_selstart] = n; + x->x_bufsize = newsize; + x->x_selstart = x->x_selstart + 1; + } + /*--moo: check for unicode codepoints beyond 7-bit ASCII --*/ + else if (n > 127) + { + int ch_nbytes = u8_wc_nbytes(n); + newsize = x->x_bufsize + ch_nbytes; + x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize); + for (i = newsize-1; i > x->x_selstart; i--) + x->x_buf[i] = x->x_buf[i-ch_nbytes]; + x->x_bufsize = newsize; + /*-- moo: assume canvas_key() has encoded keysym as UTF-8 */ + strncpy(x->x_buf+x->x_selstart, keysym->s_name, ch_nbytes); + x->x_selstart = x->x_selstart + ch_nbytes; + } + x->x_selend = x->x_selstart; + x->x_glist->gl_editor->e_textdirty = 1; + } + else if (!strcmp(keysym->s_name, "Right")) + { + if (x->x_selend == x->x_selstart && x->x_selstart < x->x_bufsize) + { + u8_inc(x->x_buf, &x->x_selstart); + x->x_selend = x->x_selstart; + } + else + x->x_selstart = x->x_selend; + } + else if (!strcmp(keysym->s_name, "Left")) + { + if (x->x_selend == x->x_selstart && x->x_selstart > 0) + { + u8_dec(x->x_buf, &x->x_selstart); + x->x_selend = x->x_selstart; + } + else + x->x_selend = x->x_selstart; + } + /* this should be improved... life's too short */ + else if (!strcmp(keysym->s_name, "Up")) + { + if (x->x_selstart) + u8_dec(x->x_buf, &x->x_selstart); + while (x->x_selstart > 0 && x->x_buf[x->x_selstart] != '\n') + u8_dec(x->x_buf, &x->x_selstart); + x->x_selend = x->x_selstart; + } + else if (!strcmp(keysym->s_name, "Down")) + { + while (x->x_selend < x->x_bufsize && + x->x_buf[x->x_selend] != '\n') + u8_inc(x->x_buf, &x->x_selend); + if (x->x_selend < x->x_bufsize) + u8_inc(x->x_buf, &x->x_selend); + x->x_selstart = x->x_selend; + } + rtext_senditup(x, SEND_UPDATE, &w, &h, &indx); +} + +void rtext_mouse(t_rtext *x, int xval, int yval, int flag) +{ + int w = xval, h = yval, indx; + rtext_senditup(x, SEND_CHECK, &w, &h, &indx); + if (flag == RTEXT_DOWN) + { + x->x_dragfrom = x->x_selstart = x->x_selend = indx; + } + else if (flag == RTEXT_DBL) + { + int whereseparator, newseparator; + x->x_dragfrom = -1; + whereseparator = 0; + if ((newseparator = lastone(x->x_buf, ' ', indx)) > whereseparator) + whereseparator = newseparator+1; + if ((newseparator = lastone(x->x_buf, '\n', indx)) > whereseparator) + whereseparator = newseparator+1; + if ((newseparator = lastone(x->x_buf, ';', indx)) > whereseparator) + whereseparator = newseparator+1; + if ((newseparator = lastone(x->x_buf, ',', indx)) > whereseparator) + whereseparator = newseparator+1; + x->x_selstart = whereseparator; + + whereseparator = x->x_bufsize - indx; + if ((newseparator = + firstone(x->x_buf+indx, ' ', x->x_bufsize - indx)) >= 0 && + newseparator < whereseparator) + whereseparator = newseparator; + if ((newseparator = + firstone(x->x_buf+indx, '\n', x->x_bufsize - indx)) >= 0 && + newseparator < whereseparator) + whereseparator = newseparator; + if ((newseparator = + firstone(x->x_buf+indx, ';', x->x_bufsize - indx)) >= 0 && + newseparator < whereseparator) + whereseparator = newseparator; + if ((newseparator = + firstone(x->x_buf+indx, ',', x->x_bufsize - indx)) >= 0 && + newseparator < whereseparator) + whereseparator = newseparator; + x->x_selend = indx + whereseparator; + } + else if (flag == RTEXT_SHIFT) + { + if (indx * 2 > x->x_selstart + x->x_selend) + x->x_dragfrom = x->x_selstart, x->x_selend = indx; + else + x->x_dragfrom = x->x_selend, x->x_selstart = indx; + } + else if (flag == RTEXT_DRAG) + { + if (x->x_dragfrom < 0) + return; + x->x_selstart = (x->x_dragfrom < indx ? x->x_dragfrom : indx); + x->x_selend = (x->x_dragfrom > indx ? x->x_dragfrom : indx); + } + rtext_senditup(x, SEND_UPDATE, &w, &h, &indx); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_scalar.c b/ports/camomile/source/LibPd/pure-data/src/g_scalar.c new file mode 100644 index 00000000..aa181717 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_scalar.c @@ -0,0 +1,452 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This file defines the "scalar" object, which is not a text object, just a +"gobj". Scalars have templates which describe their structures, which +can contain numbers, sublists, and arrays. + +*/ + +#include +#include +#include /* for read/write to files */ +#include "m_pd.h" +#include "g_canvas.h" + +t_class *scalar_class; + +void word_init(t_word *wp, t_template *template, t_gpointer *gp) +{ + int i, nitems = template->t_n; + t_dataslot *datatypes = template->t_vec; + for (i = 0; i < nitems; i++, datatypes++, wp++) + { + int type = datatypes->ds_type; + if (type == DT_FLOAT) + wp->w_float = 0; + else if (type == DT_SYMBOL) + wp->w_symbol = &s_symbol; + else if (type == DT_ARRAY) + wp->w_array = array_new(datatypes->ds_arraytemplate, gp); + else if (type == DT_TEXT) + wp->w_binbuf = binbuf_new(); + } +} + +void word_restore(t_word *wp, t_template *template, + int argc, t_atom *argv) +{ + int i, nitems = template->t_n; + t_dataslot *datatypes = template->t_vec; + for (i = 0; i < nitems; i++, datatypes++, wp++) + { + int type = datatypes->ds_type; + if (type == DT_FLOAT) + { + t_float f; + if (argc) + { + f = atom_getfloat(argv); + argv++, argc--; + } + else f = 0; + wp->w_float = f; + } + else if (type == DT_SYMBOL) + { + t_symbol *s; + if (argc) + { + s = atom_getsymbol(argv); + argv++, argc--; + } + else s = &s_; + wp->w_symbol = s; + } + } + if (argc) + post("warning: word_restore: extra arguments"); +} + +void word_free(t_word *wp, t_template *template) +{ + int i; + t_dataslot *dt; + for (dt = template->t_vec, i = 0; i < template->t_n; i++, dt++) + { + if (dt->ds_type == DT_ARRAY) + array_free(wp[i].w_array); + else if (dt->ds_type == DT_TEXT) + binbuf_free(wp[i].w_binbuf); + } +} + +static int template_cancreate(t_template *template) +{ + int i, type, nitems = template->t_n; + t_dataslot *datatypes = template->t_vec; + t_template *elemtemplate; + for (i = 0; i < nitems; i++, datatypes++) + if (datatypes->ds_type == DT_ARRAY && + (!(elemtemplate = template_findbyname(datatypes->ds_arraytemplate)) + || !template_cancreate(elemtemplate))) + { + error("%s: no such template", datatypes->ds_arraytemplate->s_name); + return (0); + } + return (1); +} + + /* make a new scalar and add to the glist. We create a "gp" here which + will be used for array items to point back here. This gp doesn't do + reference counting or "validation" updates though; the parent won't go away + without the contained arrays going away too. The "gp" is copied out + by value in the word_init() routine so we can throw our copy away. */ + +t_scalar *scalar_new(t_glist *owner, t_symbol *templatesym) +{ + t_scalar *x; + t_template *template; + t_gpointer gp; + gpointer_init(&gp); + template = template_findbyname(templatesym); + if (!template) + { + error("scalar: couldn't find template %s", templatesym->s_name); + return (0); + } + if (!template_cancreate(template)) + return (0); + x = (t_scalar *)getbytes(sizeof(t_scalar) + + (template->t_n - 1) * sizeof(*x->sc_vec)); + x->sc_gobj.g_pd = scalar_class; + x->sc_template = templatesym; + gpointer_setglist(&gp, owner, x); + word_init(x->sc_vec, template, &gp); + return (x); +} + + /* Pd method to create a new scalar, add it to a glist, and initialize + it from the message arguments. */ + +void glist_scalar(t_glist *glist, + t_symbol *classname, int argc, t_atom *argv) +{ + t_symbol *templatesym = + canvas_makebindsym(atom_getsymbolarg(0, argc, argv)); + t_binbuf *b; + int natoms, nextmsg = 0; + t_atom *vec; + if (!template_findbyname(templatesym)) + { + pd_error(glist, "%s: no such template", + atom_getsymbolarg(0, argc, argv)->s_name); + return; + } + + b = binbuf_new(); + binbuf_restore(b, argc, argv); + natoms = binbuf_getnatom(b); + vec = binbuf_getvec(b); + canvas_readscalar(glist, natoms, vec, &nextmsg, 0); + binbuf_free(b); +} + +/* -------------------- widget behavior for scalar ------------ */ +void scalar_getbasexy(t_scalar *x, t_float *basex, t_float *basey) +{ + t_template *template = template_findbyname(x->sc_template); + *basex = template_getfloat(template, gensym("x"), x->sc_vec, 0); + *basey = template_getfloat(template, gensym("y"), x->sc_vec, 0); +} + +static void scalar_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_scalar *x = (t_scalar *)z; + t_template *template = template_findbyname(x->sc_template); + t_canvas *templatecanvas = template_findcanvas(template); + int x1 = 0x7fffffff, x2 = -0x7fffffff, y1 = 0x7fffffff, y2 = -0x7fffffff; + t_gobj *y; + t_float basex, basey; + scalar_getbasexy(x, &basex, &basey); + /* if someone deleted the template canvas, we're just a point */ + if (!templatecanvas) + { + x1 = x2 = glist_xtopixels(owner, basex); + y1 = y2 = glist_ytopixels(owner, basey); + } + else + { + x1 = y1 = 0x7fffffff; + x2 = y2 = -0x7fffffff; + for (y = templatecanvas->gl_list; y; y = y->g_next) + { + const t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd); + int nx1, ny1, nx2, ny2; + if (!wb) continue; + (*wb->w_parentgetrectfn)(y, owner, + x->sc_vec, template, basex, basey, + &nx1, &ny1, &nx2, &ny2); + if (nx1 < x1) x1 = nx1; + if (ny1 < y1) y1 = ny1; + if (nx2 > x2) x2 = nx2; + if (ny2 > y2) y2 = ny2; + } + if (x2 < x1 || y2 < y1) + x1 = y1 = x2 = y2 = 0; + } + /* post("scalar x1 %d y1 %d x2 %d y2 %d", x1, y1, x2, y2); */ + *xp1 = x1; + *yp1 = y1; + *xp2 = x2; + *yp2 = y2; +} + +static void scalar_drawselectrect(t_scalar *x, t_glist *glist, int state) +{ + if (state) + { + int x1, y1, x2, y2; + + scalar_getrect(&x->sc_gobj, glist, &x1, &y1, &x2, &y2); + x1--; x2++; y1--; y2++; + sys_vgui(".x%lx.c create line %d %d %d %d %d %d %d %d %d %d \ + -width 0 -fill blue -tags select%lx\n", + glist_getcanvas(glist), x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, + x); + } + else + { + sys_vgui(".x%lx.c delete select%lx\n", glist_getcanvas(glist), x); + } +} + +static void scalar_select(t_gobj *z, t_glist *owner, int state) +{ + t_scalar *x = (t_scalar *)z; + t_template *tmpl; + t_symbol *templatesym = x->sc_template; + t_atom at; + t_gpointer gp; + gpointer_init(&gp); + gpointer_setglist(&gp, owner, x); + SETPOINTER(&at, &gp); + if ((tmpl = template_findbyname(templatesym))) + template_notify(tmpl, (state ? gensym("select") : gensym("deselect")), + 1, &at); + gpointer_unset(&gp); + scalar_drawselectrect(x, owner, state); +} + +static void scalar_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_scalar *x = (t_scalar *)z; + t_symbol *templatesym = x->sc_template; + t_template *template = template_findbyname(templatesym); + t_symbol *zz; + t_atom at[3]; + t_gpointer gp; + int xonset, yonset, xtype, ytype, gotx, goty; + if (!template) + { + error("scalar: couldn't find template %s", templatesym->s_name); + return; + } + gotx = template_find_field(template, gensym("x"), &xonset, &xtype, &zz); + if (gotx && (xtype != DT_FLOAT)) + gotx = 0; + goty = template_find_field(template, gensym("y"), &yonset, &ytype, &zz); + if (goty && (ytype != DT_FLOAT)) + goty = 0; + if (gotx) + *(t_float *)(((char *)(x->sc_vec)) + xonset) += + dx * (glist_pixelstox(glist, 1) - glist_pixelstox(glist, 0)); + if (goty) + *(t_float *)(((char *)(x->sc_vec)) + yonset) += + dy * (glist_pixelstoy(glist, 1) - glist_pixelstoy(glist, 0)); + gpointer_init(&gp); + gpointer_setglist(&gp, glist, x); + SETPOINTER(&at[0], &gp); + SETFLOAT(&at[1], (t_float)dx); + SETFLOAT(&at[2], (t_float)dy); + template_notify(template, gensym("displace"), 2, at); + scalar_redraw(x, glist); +} + +static void scalar_activate(t_gobj *z, t_glist *owner, int state) +{ + /* post("scalar_activate %d", state); */ + /* later */ +} + +static void scalar_delete(t_gobj *z, t_glist *glist) +{ + /* nothing to do */ +} + +static void scalar_vis(t_gobj *z, t_glist *owner, int vis) +{ + t_scalar *x = (t_scalar *)z; + t_template *template = template_findbyname(x->sc_template); + t_canvas *templatecanvas = template_findcanvas(template); + t_gobj *y; + t_float basex, basey; + scalar_getbasexy(x, &basex, &basey); + /* if we don't know how to draw it, make a small rectangle */ + if (!templatecanvas) + { + if (vis) + { + int x1 = glist_xtopixels(owner, basex); + int y1 = glist_ytopixels(owner, basey); + sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags scalar%lx\n", + glist_getcanvas(owner), x1-1, y1-1, x1+1, y1+1, x); + } + else sys_vgui(".x%lx.c delete scalar%lx\n", glist_getcanvas(owner), x); + return; + } + + for (y = templatecanvas->gl_list; y; y = y->g_next) + { + const t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd); + if (!wb) continue; + (*wb->w_parentvisfn)(y, owner, x->sc_vec, template, basex, basey, vis); + } + if (glist_isselected(owner, &x->sc_gobj)) + { + scalar_drawselectrect(x, owner, 0); + scalar_drawselectrect(x, owner, 1); + } + sys_unqueuegui(x); +} + +static void scalar_doredraw(t_gobj *client, t_glist *glist) +{ + if (glist_isvisible(glist)) + { + scalar_vis(client, glist, 0); + scalar_vis(client, glist, 1); + } +} + +void scalar_redraw(t_scalar *x, t_glist *glist) +{ + if (glist_isvisible(glist)) + sys_queuegui(x, glist, scalar_doredraw); +} + +extern void template_notifyforscalar(t_template *template, t_glist *owner, + t_scalar *sc, t_symbol *s, int argc, t_atom *argv); + +int scalar_doclick(t_word *data, t_template *template, t_scalar *sc, + t_array *ap, struct _glist *owner, + t_float xloc, t_float yloc, int xpix, int ypix, + int shift, int alt, int dbl, int doit) +{ + int hit = 0; + t_canvas *templatecanvas = template_findcanvas(template); + t_gobj *y; + t_atom at[2]; + t_float basex = template_getfloat(template, gensym("x"), data, 0); + t_float basey = template_getfloat(template, gensym("y"), data, 0); + SETFLOAT(at, basex + xloc); + SETFLOAT(at+1, basey + yloc); + if (doit) + template_notifyforscalar(template, owner, + sc, gensym("click"), 2, at); + for (y = templatecanvas->gl_list; y; y = y->g_next) + { + const t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd); + if (!wb) continue; + if ((hit = (*wb->w_parentclickfn)(y, owner, + data, template, sc, ap, basex + xloc, basey + yloc, + xpix, ypix, shift, alt, dbl, doit))) + return (hit); + } + return (0); +} + +static int scalar_click(t_gobj *z, struct _glist *owner, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_scalar *x = (t_scalar *)z; + t_template *template = template_findbyname(x->sc_template); + return (scalar_doclick(x->sc_vec, template, x, 0, + owner, 0, 0, xpix, ypix, shift, alt, dbl, doit)); +} + +static void scalar_save(t_gobj *z, t_binbuf *b) +{ + t_scalar *x = (t_scalar *)z; + t_binbuf *b2 = binbuf_new(); + t_atom a, *argv; + int i, argc; + canvas_writescalar(x->sc_template, x->sc_vec, b2, 0); + binbuf_addv(b, "ss", &s__X, gensym("scalar")); + binbuf_addbinbuf(b, b2); + binbuf_addsemi(b); + binbuf_free(b2); +} + +static void scalar_properties(t_gobj *z, struct _glist *owner) +{ + t_scalar *x = (t_scalar *)z; + char *buf, buf2[80]; + int bufsize; + t_binbuf *b; + glist_noselect(owner); + glist_select(owner, z); + b = glist_writetobinbuf(owner, 0); + binbuf_gettext(b, &buf, &bufsize); + binbuf_free(b); + buf = t_resizebytes(buf, bufsize, bufsize+1); + buf[bufsize] = 0; + sprintf(buf2, "pdtk_data_dialog %%s {"); + gfxstub_new((t_pd *)owner, x, buf2); + sys_gui(buf); + sys_gui("}\n"); + t_freebytes(buf, bufsize+1); +} + +static const t_widgetbehavior scalar_widgetbehavior = +{ + scalar_getrect, + scalar_displace, + scalar_select, + scalar_activate, + scalar_delete, + scalar_vis, + scalar_click, +}; + +static void scalar_free(t_scalar *x) +{ + int i; + t_dataslot *datatypes, *dt; + t_symbol *templatesym = x->sc_template; + t_template *template = template_findbyname(templatesym); + sys_unqueuegui(x); + if (!template) + { + error("scalar: couldn't find template %s", templatesym->s_name); + return; + } + word_free(x->sc_vec, template); + gfxstub_deleteforkey(x); + /* the "size" field in the class is zero, so Pd doesn't try to free + us automatically (see pd_free()) */ + freebytes(x, sizeof(t_scalar) + (template->t_n - 1) * sizeof(*x->sc_vec)); +} + +/* ----------------- setup function ------------------- */ + +void g_scalar_setup(void) +{ + scalar_class = class_new(gensym("scalar"), 0, (t_method)scalar_free, 0, + CLASS_GOBJ, 0); + class_setwidget(scalar_class, &scalar_widgetbehavior); + class_setsavefn(scalar_class, scalar_save); + class_setpropertiesfn(scalar_class, scalar_properties); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_template.c b/ports/camomile/source/LibPd/pure-data/src/g_template.c new file mode 100644 index 00000000..9e28231e --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_template.c @@ -0,0 +1,2772 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include +#include +#include + +#include "m_pd.h" +#include "g_canvas.h" + +/* +This file contains text objects you would put in a canvas to define a +template. Templates describe objects of type "array" (g_array.c) and +"scalar" (g_scalar.c). +*/ + + /* the structure of a "struct" object (also the obsolete "gtemplate" + you get when using the name "template" in a box.) */ + +struct _gtemplate +{ + t_object x_obj; + t_template *x_template; + t_canvas *x_owner; + t_symbol *x_sym; + struct _gtemplate *x_next; + int x_argc; + t_atom *x_argv; +}; + +struct _instancetemplate +{ + int curve_motion_field; + t_float curve_motion_xcumulative; + t_float curve_motion_xbase; + t_float curve_motion_xper; + t_float curve_motion_ycumulative; + t_float curve_motion_ybase; + t_float curve_motion_yper; + t_glist *curve_motion_glist; + t_scalar *curve_motion_scalar; + t_array *curve_motion_array; + t_word *curve_motion_wp; + t_template *curve_motion_template; + t_gpointer curve_motion_gpointer; + t_float array_motion_xcumulative; + t_float array_motion_ycumulative; + t_fielddesc *array_motion_xfield; + t_fielddesc *array_motion_yfield; + t_glist *array_motion_glist; + t_scalar *array_motion_scalar; + t_array *array_motion_array; + t_word *array_motion_wp; + t_template *array_motion_template; + int array_motion_npoints; + int array_motion_elemsize; + int array_motion_altkey; + t_float array_motion_initx; + t_float array_motion_xperpix; + t_float array_motion_yperpix; + int array_motion_lastx; + int array_motion_fatten; + t_float drawnumber_motion_ycumulative; + t_glist *drawnumber_motion_glist; + t_scalar *drawnumber_motion_scalar; + t_array *drawnumber_motion_array; + t_word *drawnumber_motion_wp; + t_template *drawnumber_motion_template; + t_gpointer drawnumber_motion_gpointer; + int drawnumber_motion_type; + int drawnumber_motion_firstkey; +}; + + +/* ---------------- forward definitions ---------------- */ + +static void template_conformarray(t_template *tfrom, t_template *tto, + int *conformaction, t_array *a); +static void template_conformglist(t_template *tfrom, t_template *tto, + t_glist *glist, int *conformaction); + +/* ---------------------- storage ------------------------- */ + +static t_class *gtemplate_class; +static t_class *template_class; + +/* there's a pre-defined "float" template. LATER should we bind this +to a symbol such as "pd-float"??? */ + + /* return true if two dataslot definitions match */ +static int dataslot_matches(t_dataslot *ds1, t_dataslot *ds2, + int nametoo) +{ + return ((!nametoo || ds1->ds_name == ds2->ds_name) && + ds1->ds_type == ds2->ds_type && + (ds1->ds_type != DT_ARRAY || + ds1->ds_arraytemplate == ds2->ds_arraytemplate)); +} + +/* -- templates, the active ingredient in gtemplates defined below. ------- */ + +t_template *template_new(t_symbol *templatesym, int argc, t_atom *argv) +{ + t_template *x = (t_template *)pd_new(template_class); + x->t_n = 0; + x->t_vec = (t_dataslot *)t_getbytes(0); + while (argc > 0) + { + int newtype, oldn, newn; + t_symbol *newname, *newarraytemplate = &s_, *newtypesym; + if (argc < 2 || argv[0].a_type != A_SYMBOL || + argv[1].a_type != A_SYMBOL) + goto bad; + newtypesym = argv[0].a_w.w_symbol; + newname = argv[1].a_w.w_symbol; + if (newtypesym == &s_float) + newtype = DT_FLOAT; + else if (newtypesym == &s_symbol) + newtype = DT_SYMBOL; + /* "list" is old name.. accepted here but never saved as such */ + else if (newtypesym == gensym("text") || newtypesym == &s_list) + newtype = DT_TEXT; + else if (newtypesym == gensym("array")) + { + if (argc < 3 || argv[2].a_type != A_SYMBOL) + { + pd_error(x, "array lacks element template or name"); + goto bad; + } + newarraytemplate = canvas_makebindsym(argv[2].a_w.w_symbol); + newtype = DT_ARRAY; + argc--; + argv++; + } + else + { + pd_error(x, "%s: no such type", newtypesym->s_name); + goto bad; + } + newn = (oldn = x->t_n) + 1; + x->t_vec = (t_dataslot *)t_resizebytes(x->t_vec, + oldn * sizeof(*x->t_vec), newn * sizeof(*x->t_vec)); + x->t_n = newn; + x->t_vec[oldn].ds_type = newtype; + x->t_vec[oldn].ds_name = newname; + x->t_vec[oldn].ds_arraytemplate = newarraytemplate; + bad: + argc -= 2; argv += 2; + } + if (*templatesym->s_name) + { + x->t_sym = templatesym; + pd_bind(&x->t_pdobj, x->t_sym); + } + else x->t_sym = templatesym; + return (x); +} + +int template_find_field(t_template *x, t_symbol *name, int *p_onset, + int *p_type, t_symbol **p_arraytype) +{ + t_template *t; + int i, n; + if (!x) + { + bug("template_find_field"); + return (0); + } + n = x->t_n; + for (i = 0; i < n; i++) + if (x->t_vec[i].ds_name == name) + { + *p_onset = i * sizeof(t_word); + *p_type = x->t_vec[i].ds_type; + *p_arraytype = x->t_vec[i].ds_arraytemplate; + return (1); + } + return (0); +} + +t_float template_getfloat(t_template *x, t_symbol *fieldname, t_word *wp, + int loud) +{ + int onset, type; + t_symbol *arraytype; + t_float val = 0; + if (template_find_field(x, fieldname, &onset, &type, &arraytype)) + { + if (type == DT_FLOAT) + val = *(t_float *)(((char *)wp) + onset); + else if (loud) error("%s.%s: not a number", + x->t_sym->s_name, fieldname->s_name); + } + else if (loud) error("%s.%s: no such field", + x->t_sym->s_name, fieldname->s_name); + return (val); +} + +void template_setfloat(t_template *x, t_symbol *fieldname, t_word *wp, + t_float f, int loud) +{ + int onset, type; + t_symbol *arraytype; + if (template_find_field(x, fieldname, &onset, &type, &arraytype)) + { + if (type == DT_FLOAT) + *(t_float *)(((char *)wp) + onset) = f; + else if (loud) error("%s.%s: not a number", + x->t_sym->s_name, fieldname->s_name); + } + else if (loud) error("%s.%s: no such field", + x->t_sym->s_name, fieldname->s_name); +} + +t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname, t_word *wp, + int loud) +{ + int onset, type; + t_symbol *arraytype; + t_symbol *val = &s_; + if (template_find_field(x, fieldname, &onset, &type, &arraytype)) + { + if (type == DT_SYMBOL) + val = *(t_symbol **)(((char *)wp) + onset); + else if (loud) error("%s.%s: not a symbol", + x->t_sym->s_name, fieldname->s_name); + } + else if (loud) error("%s.%s: no such field", + x->t_sym->s_name, fieldname->s_name); + return (val); +} + +void template_setsymbol(t_template *x, t_symbol *fieldname, t_word *wp, + t_symbol *s, int loud) +{ + int onset, type; + t_symbol *arraytype; + if (template_find_field(x, fieldname, &onset, &type, &arraytype)) + { + if (type == DT_SYMBOL) + *(t_symbol **)(((char *)wp) + onset) = s; + else if (loud) error("%s.%s: not a symbol", + x->t_sym->s_name, fieldname->s_name); + } + else if (loud) error("%s.%s: no such field", + x->t_sym->s_name, fieldname->s_name); +} + + /* stringent check to see if a "saved" template, x2, matches the current + one (x1). It's OK if x1 has additional scalar elements but not (yet) + arrays. This is used for reading in "data files". */ +int template_match(t_template *x1, t_template *x2) +{ + int i; + if (x1->t_n < x2->t_n) + return (0); + for (i = x2->t_n; i < x1->t_n; i++) + { + if (x1->t_vec[i].ds_type == DT_ARRAY) + return (0); + } + if (x2->t_n > x1->t_n) + post("add elements..."); + for (i = 0; i < x2->t_n; i++) + if (!dataslot_matches(&x1->t_vec[i], &x2->t_vec[i], 1)) + return (0); + return (1); +} + +/* --------------- CONFORMING TO CHANGES IN A TEMPLATE ------------ */ + +/* the following routines handle updating scalars to agree with changes +in their template. The old template is assumed to be the "installed" one +so we can delete old items; but making new ones we have to avoid scalar_new +which would make an old one whereas we will want a new one (but whose array +elements might still be old ones.) + LATER deal with graphics updates too... */ + + /* conform the word vector of a scalar to the new template */ +static void template_conformwords(t_template *tfrom, t_template *tto, + int *conformaction, t_word *wfrom, t_word *wto) +{ + int nfrom = tfrom->t_n, nto = tto->t_n, i; + for (i = 0; i < nto; i++) + { + if (conformaction[i] >= 0) + { + /* we swap the two, in case it's an array or list, so that + when "wfrom" is deleted the old one gets cleaned up. */ + t_word wwas = wto[i]; + wto[i] = wfrom[conformaction[i]]; + wfrom[conformaction[i]] = wwas; + } + } +} + + /* conform a scalar, recursively conforming arrays */ +static t_scalar *template_conformscalar(t_template *tfrom, t_template *tto, + int *conformaction, t_glist *glist, t_scalar *scfrom) +{ + t_scalar *x; + t_gpointer gp; + int nto = tto->t_n, nfrom = tfrom->t_n, i; + t_template *scalartemplate; + /* post("conform scalar"); */ + /* possibly replace the scalar */ + if (scfrom->sc_template == tfrom->t_sym) + { + /* see scalar_new() for comment about the gpointer. */ + gpointer_init(&gp); + x = (t_scalar *)getbytes(sizeof(t_scalar) + + (tto->t_n - 1) * sizeof(*x->sc_vec)); + x->sc_gobj.g_pd = scalar_class; + x->sc_template = tfrom->t_sym; + gpointer_setglist(&gp, glist, x); + /* Here we initialize to the new template, but array and list + elements will still belong to old template. */ + word_init(x->sc_vec, tto, &gp); + + template_conformwords(tfrom, tto, conformaction, + scfrom->sc_vec, x->sc_vec); + + /* replace the old one with the new one in the list */ + if (glist->gl_list == &scfrom->sc_gobj) + { + glist->gl_list = &x->sc_gobj; + x->sc_gobj.g_next = scfrom->sc_gobj.g_next; + } + else + { + t_gobj *y, *y2; + for (y = glist->gl_list; (y2 = y->g_next); y = y2) + if (y2 == &scfrom->sc_gobj) + { + x->sc_gobj.g_next = y2->g_next; + y->g_next = &x->sc_gobj; + goto nobug; + } + bug("template_conformscalar"); + nobug: ; + } + /* burn the old one */ + pd_free(&scfrom->sc_gobj.g_pd); + scalartemplate = tto; + } + else + { + x = scfrom; + scalartemplate = template_findbyname(x->sc_template); + } + /* convert all array elements */ + for (i = 0; i < scalartemplate->t_n; i++) + { + t_dataslot *ds = scalartemplate->t_vec + i; + if (ds->ds_type == DT_ARRAY) + { + template_conformarray(tfrom, tto, conformaction, + x->sc_vec[i].w_array); + } + } + return (x); +} + + /* conform an array, recursively conforming sublists and arrays */ +static void template_conformarray(t_template *tfrom, t_template *tto, + int *conformaction, t_array *a) +{ + int i, j; + t_template *scalartemplate = 0; + if (a->a_templatesym == tfrom->t_sym) + { + /* the array elements must all be conformed */ + int oldelemsize = sizeof(t_word) * tfrom->t_n, + newelemsize = sizeof(t_word) * tto->t_n; + char *newarray = getbytes(newelemsize * a->a_n); + char *oldarray = a->a_vec; + if (a->a_elemsize != oldelemsize) + bug("template_conformarray"); + for (i = 0; i < a->a_n; i++) + { + t_word *wp = (t_word *)(newarray + newelemsize * i); + word_init(wp, tto, &a->a_gp); + template_conformwords(tfrom, tto, conformaction, + (t_word *)(oldarray + oldelemsize * i), wp); + word_free((t_word *)(oldarray + oldelemsize * i), tfrom); + } + scalartemplate = tto; + a->a_vec = newarray; + freebytes(oldarray, oldelemsize * a->a_n); + } + else scalartemplate = template_findbyname(a->a_templatesym); + /* convert all arrays and sublist fields in each element of the array */ + for (i = 0; i < a->a_n; i++) + { + t_word *wp = (t_word *)(a->a_vec + sizeof(t_word) * a->a_n * i); + for (j = 0; j < scalartemplate->t_n; j++) + { + t_dataslot *ds = scalartemplate->t_vec + j; + if (ds->ds_type == DT_ARRAY) + { + template_conformarray(tfrom, tto, conformaction, + wp[j].w_array); + } + } + } +} + + /* this routine searches for every scalar in the glist that belongs + to the "from" template and makes it belong to the "to" template. Descend + glists recursively. + We don't handle redrawing here; this is to be filled in LATER... */ + +t_array *garray_getarray(t_garray *x); + +static void template_conformglist(t_template *tfrom, t_template *tto, + t_glist *glist, int *conformaction) +{ + t_gobj *g; + /* post("conform glist %s", glist->gl_name->s_name); */ + for (g = glist->gl_list; g; g = g->g_next) + { + if (pd_class(&g->g_pd) == scalar_class) + g = &template_conformscalar(tfrom, tto, conformaction, + glist, (t_scalar *)g)->sc_gobj; + else if (pd_class(&g->g_pd) == canvas_class) + template_conformglist(tfrom, tto, (t_glist *)g, conformaction); + else if (pd_class(&g->g_pd) == garray_class) + template_conformarray(tfrom, tto, conformaction, + garray_getarray((t_garray *)g)); + } +} + + /* globally conform all scalars from one template to another */ +void template_conform(t_template *tfrom, t_template *tto) +{ + int nto = tto->t_n, nfrom = tfrom->t_n, i, j, + *conformaction = (int *)getbytes(sizeof(int) * nto), + *conformedfrom = (int *)getbytes(sizeof(int) * nfrom), doit = 0; + for (i = 0; i < nto; i++) + conformaction[i] = -1; + for (i = 0; i < nfrom; i++) + conformedfrom[i] = 0; + for (i = 0; i < nto; i++) + { + t_dataslot *dataslot = &tto->t_vec[i]; + for (j = 0; j < nfrom; j++) + { + t_dataslot *dataslot2 = &tfrom->t_vec[j]; + if (dataslot_matches(dataslot, dataslot2, 1)) + { + conformaction[i] = j; + conformedfrom[j] = 1; + } + } + } + for (i = 0; i < nto; i++) + if (conformaction[i] < 0) + { + t_dataslot *dataslot = &tto->t_vec[i]; + for (j = 0; j < nfrom; j++) + if (!conformedfrom[j] && + dataslot_matches(dataslot, &tfrom->t_vec[j], 0)) + { + conformaction[i] = j; + conformedfrom[j] = 1; + } + } + if (nto != nfrom) + doit = 1; + else for (i = 0; i < nto; i++) + if (conformaction[i] != i) + doit = 1; + + if (doit) + { + t_glist *gl; + for (gl = pd_getcanvaslist(); gl; gl = gl->gl_next) + template_conformglist(tfrom, tto, gl, conformaction); + } + freebytes(conformaction, sizeof(int) * nto); + freebytes(conformedfrom, sizeof(int) * nfrom); +} + +t_template *template_findbyname(t_symbol *s) +{ + return ((t_template *)pd_findbyclass(s, template_class)); +} + +t_canvas *template_findcanvas(t_template *template) +{ + t_gtemplate *gt; + if (!template) + bug("template_findcanvas"); + if (!(gt = template->t_list)) + return (0); + return (gt->x_owner); + /* return ((t_canvas *)pd_findbyclass(template->t_sym, canvas_class)); */ +} + +void template_notify(t_template *template, t_symbol *s, int argc, t_atom *argv) +{ + if (template->t_list) + outlet_anything(template->t_list->x_obj.ob_outlet, s, argc, argv); +} + + /* bash the first of (argv) with a pointer to a scalar, and send on + to template as a notification message */ +void template_notifyforscalar(t_template *template, t_glist *owner, + t_scalar *sc, t_symbol *s, int argc, t_atom *argv) +{ + t_gpointer gp; + gpointer_init(&gp); + gpointer_setglist(&gp, owner, sc); + SETPOINTER(argv, &gp); + template_notify(template, s, argc, argv); + gpointer_unset(&gp); +} + + /* call this when reading a patch from a file to declare what templates + we'll need. If there's already a template, check if it matches. + If it doesn't it's still OK as long as there are no "struct" (gtemplate) + objects hanging from it; we just conform everyone to the new template. + If there are still struct objects belonging to the other template, we're + in trouble. LATER we'll figure out how to conform the new patch's objects + to the pre-existing struct. */ +static void *template_usetemplate(void *dummy, t_symbol *s, + int argc, t_atom *argv) +{ + t_template *x; + t_symbol *templatesym = + canvas_makebindsym(atom_getsymbolarg(0, argc, argv)); + if (!argc) + return (0); + argc--; argv++; + /* check if there's already a template by this name. */ + if ((x = (t_template *)pd_findbyclass(templatesym, template_class))) + { + t_template *y = template_new(&s_, argc, argv), *y2; + /* If the new template is the same as the old one, + there's nothing to do. */ + if (!template_match(x, y)) + { + /* Are there "struct" objects upholding this template? */ + if (x->t_list) + { + /* don't know what to do here! */ + error("%s: template mismatch", + templatesym->s_name); + } + else + { + /* conform everyone to the new template */ + template_conform(x, y); + pd_free(&x->t_pdobj); + y2 = template_new(templatesym, argc, argv); + y2->t_list = 0; + } + } + pd_free(&y->t_pdobj); + } + /* otherwise, just make one. */ + else template_new(templatesym, argc, argv); + return (0); +} + + /* here we assume someone has already cleaned up all instances of this. */ +void template_free(t_template *x) +{ + if (*x->t_sym->s_name) + pd_unbind(&x->t_pdobj, x->t_sym); + t_freebytes(x->t_vec, x->t_n * sizeof(*x->t_vec)); +} + +static void template_setup(void) +{ + template_class = class_new(gensym("template"), 0, (t_method)template_free, + sizeof(t_template), CLASS_PD, 0); + class_addmethod(pd_canvasmaker, (t_method)template_usetemplate, + gensym("struct"), A_GIMME, 0); + +} + +/* ---------------- gtemplates. One per canvas. ----------- */ + +/* "Struct": an object that searches for, and if necessary creates, +a template (above). Other objects in the canvas then can give drawing +instructions for the template. The template doesn't go away when the +"struct" is deleted, so that you can replace it with +another one to add new fields, for example. */ + +static void *gtemplate_donew(t_symbol *sym, int argc, t_atom *argv) +{ + t_gtemplate *x = (t_gtemplate *)pd_new(gtemplate_class); + t_template *t = template_findbyname(sym); + int i; + t_symbol *sx = gensym("x"); + x->x_owner = canvas_getcurrent(); + x->x_next = 0; + x->x_sym = sym; + x->x_argc = argc; + x->x_argv = (t_atom *)getbytes(argc * sizeof(t_atom)); + for (i = 0; i < argc; i++) + x->x_argv[i] = argv[i]; + + /* already have a template by this name? */ + if (t) + { + x->x_template = t; + /* if it's already got a "struct" object we + just tack this one to the end of the list and leave it + there. */ + if (t->t_list) + { + t_gtemplate *x2, *x3; + for (x2 = x->x_template->t_list; (x3 = x2->x_next); x2 = x3) + ; + x2->x_next = x; + post("template %s: warning: already exists.", sym->s_name); + } + else + { + /* if there's none, we just replace the template with + our own and conform it. */ + t_template *y = template_new(&s_, argc, argv); + canvas_redrawallfortemplate(t, 2); + /* Unless the new template is different from the old one, + there's nothing to do. */ + if (!template_match(t, y)) + { + /* conform everyone to the new template */ + template_conform(t, y); + pd_free(&t->t_pdobj); + x->x_template = t = template_new(sym, argc, argv); + } + pd_free(&y->t_pdobj); + t->t_list = x; + canvas_redrawallfortemplate(t, 1); + } + } + else + { + /* otherwise make a new one and we're the only struct on it. */ + x->x_template = t = template_new(sym, argc, argv); + t->t_list = x; + } + outlet_new(&x->x_obj, 0); + return (x); +} + +static void *gtemplate_new(t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *sym = atom_getsymbolarg(0, argc, argv); + if (argc >= 1) + argc--, argv++; + if (sym->s_name[0] == '-') + post("warning: struct '%s' initial '-' may confuse get/set, etc.", + sym->s_name); + return (gtemplate_donew(canvas_makebindsym(sym), argc, argv)); +} + + /* old version (0.34) -- delete 2003 or so */ +static void *gtemplate_new_old(t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *sym = canvas_makebindsym(canvas_getcurrent()->gl_name); + static int warned; + if (!warned) + { + post("warning -- 'template' (%s) is obsolete; replace with 'struct'", + sym->s_name); + warned = 1; + } + return (gtemplate_donew(sym, argc, argv)); +} + +t_template *gtemplate_get(t_gtemplate *x) +{ + return (x->x_template); +} + +static void gtemplate_free(t_gtemplate *x) +{ + /* get off the template's list */ + t_template *t = x->x_template; + t_gtemplate *y; + if (x == t->t_list) + { + canvas_redrawallfortemplate(t, 2); + if (x->x_next) + { + /* if we were first on the list, and there are others on + the list, make a new template corresponding to the new + first-on-list and replace the existing template with it. */ + t_template *z = template_new(&s_, + x->x_next->x_argc, x->x_next->x_argv); + template_conform(t, z); + pd_free(&t->t_pdobj); + pd_free(&z->t_pdobj); + z = template_new(x->x_sym, x->x_next->x_argc, x->x_next->x_argv); + z->t_list = x->x_next; + for (y = z->t_list; y ; y = y->x_next) + y->x_template = z; + } + else t->t_list = 0; + canvas_redrawallfortemplate(t, 1); + } + else + { + t_gtemplate *x2, *x3; + for (x2 = t->t_list; (x3 = x2->x_next); x2 = x3) + { + if (x == x3) + { + x2->x_next = x3->x_next; + break; + } + } + } + freebytes(x->x_argv, sizeof(t_atom) * x->x_argc); +} + +static void gtemplate_setup(void) +{ + gtemplate_class = class_new(gensym("struct"), + (t_newmethod)gtemplate_new, (t_method)gtemplate_free, + sizeof(t_gtemplate), CLASS_NOINLET, A_GIMME, 0); + class_addcreator((t_newmethod)gtemplate_new_old, gensym("template"), + A_GIMME, 0); +} + +/* --------------- FIELD DESCRIPTORS ---------------------- */ + +/* a field descriptor can hold a constant or a variable; if a variable, +it's the name of a field in the template we belong to. LATER, we might +want to cache the offset of the field so we don't have to search for it +every single time we draw the object. +*/ + +struct _fielddesc +{ + char fd_type; /* LATER consider removing this? */ + char fd_var; + union + { + t_float fd_float; /* the field is a constant float */ + t_symbol *fd_symbol; /* the field is a constant symbol */ + t_symbol *fd_varsym; /* the field is variable and this is the name */ + } fd_un; + float fd_v1; /* min and max values */ + float fd_v2; + float fd_screen1; /* min and max screen values */ + float fd_screen2; + float fd_quantum; /* quantization in value */ +}; + +static void fielddesc_setfloat_const(t_fielddesc *fd, t_float f) +{ + fd->fd_type = A_FLOAT; + fd->fd_var = 0; + fd->fd_un.fd_float = f; + fd->fd_v1 = fd->fd_v2 = fd->fd_screen1 = fd->fd_screen2 = + fd->fd_quantum = 0; +} + +static void fielddesc_setsymbol_const(t_fielddesc *fd, t_symbol *s) +{ + fd->fd_type = A_SYMBOL; + fd->fd_var = 0; + fd->fd_un.fd_symbol = s; + fd->fd_v1 = fd->fd_v2 = fd->fd_screen1 = fd->fd_screen2 = + fd->fd_quantum = 0; +} + +static void fielddesc_setfloat_var(t_fielddesc *fd, t_symbol *s) +{ + char *s1, *s2, *s3, strbuf[MAXPDSTRING]; + int i; + fd->fd_type = A_FLOAT; + fd->fd_var = 1; + if (!(s1 = strchr(s->s_name, '(')) || !(s2 = strchr(s->s_name, ')')) + || (s1 > s2)) + { + fd->fd_un.fd_varsym = s; + fd->fd_v1 = fd->fd_v2 = fd->fd_screen1 = fd->fd_screen2 = + fd->fd_quantum = 0; + } + else + { + int cpy = (int)(s1 - s->s_name), got; + double v1, v2, screen1, screen2, quantum; + if (cpy > MAXPDSTRING-5) + cpy = MAXPDSTRING-5; + strncpy(strbuf, s->s_name, cpy); + strbuf[cpy] = 0; + fd->fd_un.fd_varsym = gensym(strbuf); + got = sscanf(s1, "(%lf:%lf)(%lf:%lf)(%lf)", + &v1, &v2, &screen1, &screen2, + &quantum); + fd->fd_v1=v1; + fd->fd_v2=v2; + fd->fd_screen1=screen1; + fd->fd_screen2=screen2; + fd->fd_quantum=quantum; + if (got < 2) + goto fail; + if (got == 3 || (got < 4 && strchr(s2, '('))) + goto fail; + if (got < 5 && (s3 = strchr(s2, '(')) && strchr(s3+1, '(')) + goto fail; + if (got == 4) + fd->fd_quantum = 0; + else if (got == 2) + { + fd->fd_quantum = 0; + fd->fd_screen1 = fd->fd_v1; + fd->fd_screen2 = fd->fd_v2; + } + return; + fail: + post("parse error: %s", s->s_name); + fd->fd_v1 = fd->fd_screen1 = fd->fd_v2 = fd->fd_screen2 = + fd->fd_quantum = 0; + } +} + +#define CLOSED 1 +#define BEZ 2 +#define NOMOUSE 4 +#define A_ARRAY 55 /* LATER decide whether to enshrine this in m_pd.h */ + +static void fielddesc_setfloatarg(t_fielddesc *fd, int argc, t_atom *argv) +{ + if (argc <= 0) fielddesc_setfloat_const(fd, 0); + else if (argv->a_type == A_SYMBOL) + fielddesc_setfloat_var(fd, argv->a_w.w_symbol); + else fielddesc_setfloat_const(fd, argv->a_w.w_float); +} + +static void fielddesc_setsymbolarg(t_fielddesc *fd, int argc, t_atom *argv) +{ + if (argc <= 0) fielddesc_setsymbol_const(fd, &s_); + else if (argv->a_type == A_SYMBOL) + { + fd->fd_type = A_SYMBOL; + fd->fd_var = 1; + fd->fd_un.fd_varsym = argv->a_w.w_symbol; + fd->fd_v1 = fd->fd_v2 = fd->fd_screen1 = fd->fd_screen2 = + fd->fd_quantum = 0; + } + else fielddesc_setsymbol_const(fd, &s_); +} + +static void fielddesc_setarrayarg(t_fielddesc *fd, int argc, t_atom *argv) +{ + if (argc <= 0) fielddesc_setfloat_const(fd, 0); + else if (argv->a_type == A_SYMBOL) + { + fd->fd_type = A_ARRAY; + fd->fd_var = 1; + fd->fd_un.fd_varsym = argv->a_w.w_symbol; + } + else fielddesc_setfloat_const(fd, argv->a_w.w_float); +} + + /* getting and setting values via fielddescs -- note confusing names; + the above are setting up the fielddesc itself. */ +static t_float fielddesc_getfloat(t_fielddesc *f, t_template *template, + t_word *wp, int loud) +{ + if (f->fd_type == A_FLOAT) + { + if (f->fd_var) + return (template_getfloat(template, f->fd_un.fd_varsym, wp, loud)); + else return (f->fd_un.fd_float); + } + else + { + if (loud) + error("symbolic data field used as number"); + return (0); + } +} + + /* convert a variable's value to a screen coordinate via its fielddesc */ +t_float fielddesc_cvttocoord(t_fielddesc *f, t_float val) +{ + t_float coord, pix, extreme, div; + if (f->fd_v2 == f->fd_v1) + return (val); + div = (f->fd_screen2 - f->fd_screen1)/(f->fd_v2 - f->fd_v1); + coord = f->fd_screen1 + (val - f->fd_v1) * div; + extreme = (f->fd_screen1 < f->fd_screen2 ? + f->fd_screen1 : f->fd_screen2); + if (coord < extreme) + coord = extreme; + extreme = (f->fd_screen1 > f->fd_screen2 ? + f->fd_screen1 : f->fd_screen2); + if (coord > extreme) + coord = extreme; + return (coord); +} + + /* read a variable via fielddesc and convert to screen coordinate */ +t_float fielddesc_getcoord(t_fielddesc *f, t_template *template, + t_word *wp, int loud) +{ + if (f->fd_type == A_FLOAT) + { + if (f->fd_var) + { + t_float val = template_getfloat(template, + f->fd_un.fd_varsym, wp, loud); + return (fielddesc_cvttocoord(f, val)); + } + else return (f->fd_un.fd_float); + } + else + { + if (loud) + error("symbolic data field used as number"); + return (0); + } +} + +static t_symbol *fielddesc_getsymbol(t_fielddesc *f, t_template *template, + t_word *wp, int loud) +{ + if (f->fd_type == A_SYMBOL) + { + if (f->fd_var) + return(template_getsymbol(template, f->fd_un.fd_varsym, wp, loud)); + else return (f->fd_un.fd_symbol); + } + else + { + if (loud) + error("numeric data field used as symbol"); + return (&s_); + } +} + + /* convert from a screen coordinate to a variable value */ +t_float fielddesc_cvtfromcoord(t_fielddesc *f, t_float coord) +{ + t_float val; + if (f->fd_screen2 == f->fd_screen1) + val = coord; + else + { + t_float div = (f->fd_v2 - f->fd_v1)/(f->fd_screen2 - f->fd_screen1); + t_float extreme; + val = f->fd_v1 + (coord - f->fd_screen1) * div; + if (f->fd_quantum != 0) + val = ((int)((val/f->fd_quantum) + 0.5)) * f->fd_quantum; + extreme = (f->fd_v1 < f->fd_v2 ? + f->fd_v1 : f->fd_v2); + if (val < extreme) val = extreme; + extreme = (f->fd_v1 > f->fd_v2 ? + f->fd_v1 : f->fd_v2); + if (val > extreme) val = extreme; + } + return (val); + } + +void fielddesc_setcoord(t_fielddesc *f, t_template *template, + t_word *wp, t_float coord, int loud) +{ + if (f->fd_type == A_FLOAT && f->fd_var) + { + t_float val = fielddesc_cvtfromcoord(f, coord); + template_setfloat(template, + f->fd_un.fd_varsym, wp, val, loud); + } + else + { + if (loud) + error("attempt to set constant or symbolic data field to a number"); + } +} + +/* ---------------- curves and polygons (joined segments) ---------------- */ + +/* +curves belong to templates and describe how the data in the template are to +be drawn. The coordinates of the curve (and other display features) can +be attached to fields in the template. +*/ + +t_class *curve_class; + +typedef struct _curve +{ + t_object x_obj; + int x_flags; /* CLOSED and/or BEZ and/or NOMOUSE */ + t_fielddesc x_fillcolor; + t_fielddesc x_outlinecolor; + t_fielddesc x_width; + t_fielddesc x_vis; + int x_npoints; + t_fielddesc *x_vec; + t_canvas *x_canvas; +} t_curve; + +static void *curve_new(t_symbol *classsym, int argc, t_atom *argv) +{ + t_curve *x = (t_curve *)pd_new(curve_class); + char *classname = classsym->s_name; + int flags = 0; + int nxy, i; + t_fielddesc *fd; + x->x_canvas = canvas_getcurrent(); + if (classname[0] == 'f') + { + classname += 6; + flags |= CLOSED; + } + else classname += 4; + if (classname[0] == 'c') flags |= BEZ; + fielddesc_setfloat_const(&x->x_vis, 1); + while (1) + { + t_symbol *firstarg = atom_getsymbolarg(0, argc, argv); + if (!strcmp(firstarg->s_name, "-v") && argc > 1) + { + fielddesc_setfloatarg(&x->x_vis, 1, argv+1); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-x")) + { + flags |= NOMOUSE; + argc -= 1; argv += 1; + } + else break; + } + x->x_flags = flags; + if ((flags & CLOSED) && argc) + fielddesc_setfloatarg(&x->x_fillcolor, argc--, argv++); + else fielddesc_setfloat_const(&x->x_fillcolor, 0); + if (argc) fielddesc_setfloatarg(&x->x_outlinecolor, argc--, argv++); + else fielddesc_setfloat_const(&x->x_outlinecolor, 0); + if (argc) fielddesc_setfloatarg(&x->x_width, argc--, argv++); + else fielddesc_setfloat_const(&x->x_width, 1); + if (argc < 0) argc = 0; + nxy = (argc + (argc & 1)); + x->x_npoints = (nxy>>1); + x->x_vec = (t_fielddesc *)t_getbytes(nxy * sizeof(t_fielddesc)); + for (i = 0, fd = x->x_vec; i < argc; i++, fd++, argv++) + fielddesc_setfloatarg(fd, 1, argv); + if (argc & 1) fielddesc_setfloat_const(fd, 0); + + return (x); +} + +void curve_float(t_curve *x, t_floatarg f) +{ + int viswas; + if (x->x_vis.fd_type != A_FLOAT || x->x_vis.fd_var) + { + pd_error(x, "global vis/invis for a template with variable visibility"); + return; + } + viswas = (x->x_vis.fd_un.fd_float != 0); + + if ((f != 0 && viswas) || (f == 0 && !viswas)) + return; + canvas_redrawallfortemplatecanvas(x->x_canvas, 2); + fielddesc_setfloat_const(&x->x_vis, (f != 0)); + canvas_redrawallfortemplatecanvas(x->x_canvas, 1); +} + +/* -------------------- widget behavior for curve ------------ */ + +static void curve_getrect(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_curve *x = (t_curve *)z; + int i, n = x->x_npoints; + t_fielddesc *f = x->x_vec; + int x1 = 0x7fffffff, x2 = -0x7fffffff, y1 = 0x7fffffff, y2 = -0x7fffffff; + if (!fielddesc_getfloat(&x->x_vis, template, data, 0) || + (x->x_flags & NOMOUSE)) + { + *xp1 = *yp1 = 0x7fffffff; + *xp2 = *yp2 = -0x7fffffff; + return; + } + for (i = 0, f = x->x_vec; i < n; i++, f += 2) + { + int xloc = glist_xtopixels(glist, + basex + fielddesc_getcoord(f, template, data, 0)); + int yloc = glist_ytopixels(glist, + basey + fielddesc_getcoord(f+1, template, data, 0)); + if (xloc < x1) x1 = xloc; + if (xloc > x2) x2 = xloc; + if (yloc < y1) y1 = yloc; + if (yloc > y2) y2 = yloc; + } + *xp1 = x1; + *yp1 = y1; + *xp2 = x2; + *yp2 = y2; +} + +static void curve_displace(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int dx, int dy) +{ + /* refuse */ +} + +static void curve_select(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int state) +{ + /* fill in later */ +} + +static void curve_activate(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int state) +{ + /* fill in later */ +} + +#if 0 +static int rangecolor(int n) /* 0 to 9 in 5 steps */ +{ + int n2 = n/2; /* 0 to 4 */ + int ret = (n2 << 6); /* 0 to 256 in 5 steps */ + if (ret > 255) ret = 255; + return (ret); +} +#endif + +static int rangecolor(int n) /* 0 to 9 in 5 steps */ +{ + int n2 = (n == 9 ? 8 : n); /* 0 to 8 */ + int ret = (n2 << 5); /* 0 to 256 in 9 steps */ + if (ret > 255) ret = 255; + return (ret); +} + +static void numbertocolor(int n, char *s) +{ + int red, blue, green; + if (n < 0) n = 0; + red = n / 100; + blue = ((n / 10) % 10); + green = n % 10; + sprintf(s, "#%2.2x%2.2x%2.2x", rangecolor(red), rangecolor(blue), + rangecolor(green)); +} + +static void curve_vis(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int vis) +{ + t_curve *x = (t_curve *)z; + int i, n = x->x_npoints; + t_fielddesc *f = x->x_vec; + + /* see comment in plot_vis() */ + if (vis && !fielddesc_getfloat(&x->x_vis, template, data, 0)) + return; + if (vis) + { + if (n > 1) + { + int flags = x->x_flags, closed = (flags & CLOSED); + t_float width = fielddesc_getfloat(&x->x_width, template, data, 1); + char outline[20], fill[20]; + int pix[200]; + if (n > 100) + n = 100; + /* calculate the pixel values before we start printing + out the TK message so that "error" printout won't be + interspersed with it. Only show up to 100 points so we don't + have to allocate memory here. */ + for (i = 0, f = x->x_vec; i < n; i++, f += 2) + { + pix[2*i] = glist_xtopixels(glist, + basex + fielddesc_getcoord(f, template, data, 1)); + pix[2*i+1] = glist_ytopixels(glist, + basey + fielddesc_getcoord(f+1, template, data, 1)); + } + if (width < 1) width = 1; + if (glist->gl_isgraph) + width *= glist_getzoom(glist); + numbertocolor( + fielddesc_getfloat(&x->x_outlinecolor, template, data, 1), + outline); + if (flags & CLOSED) + { + numbertocolor( + fielddesc_getfloat(&x->x_fillcolor, template, data, 1), + fill); + sys_vgui(".x%lx.c create polygon\\\n", + glist_getcanvas(glist)); + } + else sys_vgui(".x%lx.c create line\\\n", glist_getcanvas(glist)); + for (i = 0; i < n; i++) + sys_vgui("%d %d\\\n", pix[2*i], pix[2*i+1]); + sys_vgui("-width %f\\\n", width); + if (flags & CLOSED) sys_vgui("-fill %s -outline %s\\\n", + fill, outline); + else sys_vgui("-fill %s\\\n", outline); + if (flags & BEZ) sys_vgui("-smooth 1\\\n"); + sys_vgui("-tags curve%lx\n", data); + } + else post("warning: curves need at least two points to be graphed"); + } + else + { + if (n > 1) sys_vgui(".x%lx.c delete curve%lx\n", + glist_getcanvas(glist), data); + } +} + + /* LATER protect against the template changing or the scalar disappearing + probably by attaching a gpointer here ... */ + +static void curve_motion(void *z, t_floatarg dx, t_floatarg dy) +{ + t_curve *x = (t_curve *)z; + t_fielddesc *f = x->x_vec + TEMPLATE->curve_motion_field; + t_atom at; + if (!gpointer_check(&TEMPLATE->curve_motion_gpointer, 0)) + { + post("curve_motion: scalar disappeared"); + return; + } + TEMPLATE->curve_motion_xcumulative += dx; + TEMPLATE->curve_motion_ycumulative += dy; + if (f->fd_var && (dx != 0)) + { + fielddesc_setcoord(f, TEMPLATE->curve_motion_template, + TEMPLATE->curve_motion_wp, + TEMPLATE->curve_motion_xbase + + TEMPLATE->curve_motion_xcumulative * TEMPLATE->curve_motion_xper, + 1); + } + if ((f+1)->fd_var && (dy != 0)) + { + fielddesc_setcoord(f+1, TEMPLATE->curve_motion_template, + TEMPLATE->curve_motion_wp, + TEMPLATE->curve_motion_ybase + + TEMPLATE->curve_motion_ycumulative * TEMPLATE->curve_motion_yper, + 1); + } + /* LATER figure out what to do to notify for an array? */ + if (TEMPLATE->curve_motion_scalar) + template_notifyforscalar(TEMPLATE->curve_motion_template, + TEMPLATE->curve_motion_glist, + TEMPLATE->curve_motion_scalar, gensym("change"), 1, &at); + if (TEMPLATE->curve_motion_scalar) + scalar_redraw(TEMPLATE->curve_motion_scalar, + TEMPLATE->curve_motion_glist); + if (TEMPLATE->curve_motion_array) + array_redraw(TEMPLATE->curve_motion_array, + TEMPLATE->curve_motion_glist); +} + +static int curve_click(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_scalar *sc, t_array *ap, + t_float basex, t_float basey, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_curve *x = (t_curve *)z; + int i, n = x->x_npoints; + int bestn = -1; + int besterror = 0x7fffffff; + t_fielddesc *f; + if (!fielddesc_getfloat(&x->x_vis, template, data, 0)) + return (0); + for (i = 0, f = x->x_vec; i < n; i++, f += 2) + { + int xval = fielddesc_getcoord(f, template, data, 0), + xloc = glist_xtopixels(glist, basex + xval); + int yval = fielddesc_getcoord(f+1, template, data, 0), + yloc = glist_ytopixels(glist, basey + yval); + int xerr = xloc - xpix, yerr = yloc - ypix; + if (!f->fd_var && !(f+1)->fd_var) + continue; + if (xerr < 0) + xerr = -xerr; + if (yerr < 0) + yerr = -yerr; + if (yerr > xerr) + xerr = yerr; + if (xerr < besterror) + { + TEMPLATE->curve_motion_xbase = xval; + TEMPLATE->curve_motion_ybase = yval; + besterror = xerr; + bestn = i; + } + } + if (besterror > 6) + return (0); + if (doit) + { + TEMPLATE->curve_motion_xper = glist_pixelstox(glist, 1) + - glist_pixelstox(glist, 0); + TEMPLATE->curve_motion_yper = glist_pixelstoy(glist, 1) + - glist_pixelstoy(glist, 0); + TEMPLATE->curve_motion_xcumulative = 0; + TEMPLATE->curve_motion_ycumulative = 0; + TEMPLATE->curve_motion_glist = glist; + TEMPLATE->curve_motion_scalar = sc; + TEMPLATE->curve_motion_array = ap; + TEMPLATE->curve_motion_wp = data; + TEMPLATE->curve_motion_field = 2*bestn; + TEMPLATE->curve_motion_template = template; + if (TEMPLATE->curve_motion_scalar) + gpointer_setglist(&TEMPLATE->curve_motion_gpointer, + TEMPLATE->curve_motion_glist, TEMPLATE->curve_motion_scalar); + else gpointer_setarray(&TEMPLATE->curve_motion_gpointer, + TEMPLATE->curve_motion_array, TEMPLATE->curve_motion_wp); + glist_grab(glist, z, curve_motion, 0, xpix, ypix); + } + return (1); +} + +const t_parentwidgetbehavior curve_widgetbehavior = +{ + curve_getrect, + curve_displace, + curve_select, + curve_activate, + curve_vis, + curve_click, +}; + +static void curve_free(t_curve *x) +{ + t_freebytes(x->x_vec, 2 * x->x_npoints * sizeof(*x->x_vec)); +} + +static void curve_setup(void) +{ + curve_class = class_new(gensym("drawpolygon"), (t_newmethod)curve_new, + (t_method)curve_free, sizeof(t_curve), 0, A_GIMME, 0); + class_setdrawcommand(curve_class); + class_addcreator((t_newmethod)curve_new, gensym("drawcurve"), + A_GIMME, 0); + class_addcreator((t_newmethod)curve_new, gensym("filledpolygon"), + A_GIMME, 0); + class_addcreator((t_newmethod)curve_new, gensym("filledcurve"), + A_GIMME, 0); + class_setparentwidget(curve_class, &curve_widgetbehavior); + class_addfloat(curve_class, curve_float); +} + +/* --------- plots for showing arrays --------------- */ + +t_class *plot_class; + +typedef struct _plot +{ + t_object x_obj; + t_canvas *x_canvas; + t_fielddesc x_outlinecolor; + t_fielddesc x_width; + t_fielddesc x_xloc; + t_fielddesc x_yloc; + t_fielddesc x_xinc; + t_fielddesc x_style; + t_fielddesc x_data; + t_fielddesc x_xpoints; + t_fielddesc x_ypoints; + t_fielddesc x_wpoints; + t_fielddesc x_vis; /* visible */ + t_fielddesc x_scalarvis; /* true if drawing the scalar at each point */ +} t_plot; + +static void *plot_new(t_symbol *classsym, int argc, t_atom *argv) +{ + t_plot *x = (t_plot *)pd_new(plot_class); + int defstyle = PLOTSTYLE_POLY; + x->x_canvas = canvas_getcurrent(); + + fielddesc_setfloat_var(&x->x_xpoints, gensym("x")); + fielddesc_setfloat_var(&x->x_ypoints, gensym("y")); + fielddesc_setfloat_var(&x->x_wpoints, gensym("w")); + + fielddesc_setfloat_const(&x->x_vis, 1); + fielddesc_setfloat_const(&x->x_scalarvis, 1); + while (1) + { + t_symbol *firstarg = atom_getsymbolarg(0, argc, argv); + if (!strcmp(firstarg->s_name, "curve") || + !strcmp(firstarg->s_name, "-c")) + { + defstyle = PLOTSTYLE_BEZ; + argc--, argv++; + } + else if (!strcmp(firstarg->s_name, "-v") && argc > 1) + { + fielddesc_setfloatarg(&x->x_vis, 1, argv+1); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-vs") && argc > 1) + { + fielddesc_setfloatarg(&x->x_scalarvis, 1, argv+1); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-x") && argc > 1) + { + fielddesc_setfloatarg(&x->x_xpoints, 1, argv+1); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-y") && argc > 1) + { + fielddesc_setfloatarg(&x->x_ypoints, 1, argv+1); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-w") && argc > 1) + { + fielddesc_setfloatarg(&x->x_wpoints, 1, argv+1); + argc -= 2; argv += 2; + } + else break; + } + if (argc) fielddesc_setarrayarg(&x->x_data, argc--, argv++); + else fielddesc_setfloat_const(&x->x_data, 1); + if (argc) fielddesc_setfloatarg(&x->x_outlinecolor, argc--, argv++); + else fielddesc_setfloat_const(&x->x_outlinecolor, 0); + if (argc) fielddesc_setfloatarg(&x->x_width, argc--, argv++); + else fielddesc_setfloat_const(&x->x_width, 1); + if (argc) fielddesc_setfloatarg(&x->x_xloc, argc--, argv++); + else fielddesc_setfloat_const(&x->x_xloc, 1); + if (argc) fielddesc_setfloatarg(&x->x_yloc, argc--, argv++); + else fielddesc_setfloat_const(&x->x_yloc, 1); + if (argc) fielddesc_setfloatarg(&x->x_xinc, argc--, argv++); + else fielddesc_setfloat_const(&x->x_xinc, 1); + if (argc) fielddesc_setfloatarg(&x->x_style, argc--, argv++); + else fielddesc_setfloat_const(&x->x_style, defstyle); + return (x); +} + +void plot_float(t_plot *x, t_floatarg f) +{ + int viswas; + if (x->x_vis.fd_type != A_FLOAT || x->x_vis.fd_var) + { + pd_error(x, "global vis/invis for a template with variable visibility"); + return; + } + viswas = (x->x_vis.fd_un.fd_float != 0); + + if ((f != 0 && viswas) || (f == 0 && !viswas)) + return; + canvas_redrawallfortemplatecanvas(x->x_canvas, 2); + fielddesc_setfloat_const(&x->x_vis, (f != 0)); + canvas_redrawallfortemplatecanvas(x->x_canvas, 1); +} + +/* -------------------- widget behavior for plot ------------ */ + + + /* get everything we'll need from the owner template of the array being + plotted. Not used for garrays, but see below */ +static int plot_readownertemplate(t_plot *x, + t_word *data, t_template *ownertemplate, + t_symbol **elemtemplatesymp, t_array **arrayp, + t_float *linewidthp, t_float *xlocp, t_float *xincp, t_float *ylocp, + t_float *stylep, t_float *visp, t_float *scalarvisp, + t_fielddesc **xfield, t_fielddesc **yfield, t_fielddesc **wfield) +{ + int arrayonset, type; + t_symbol *elemtemplatesym; + t_array *array; + + /* find the data and verify it's an array */ + if (x->x_data.fd_type != A_ARRAY || !x->x_data.fd_var) + { + error("plot: needs an array field"); + return (-1); + } + if (!template_find_field(ownertemplate, x->x_data.fd_un.fd_varsym, + &arrayonset, &type, &elemtemplatesym)) + { + error("plot: %s: no such field", x->x_data.fd_un.fd_varsym->s_name); + return (-1); + } + if (type != DT_ARRAY) + { + error("plot: %s: not an array", x->x_data.fd_un.fd_varsym->s_name); + return (-1); + } + array = *(t_array **)(((char *)data) + arrayonset); + *linewidthp = fielddesc_getfloat(&x->x_width, ownertemplate, data, 1); + *xlocp = fielddesc_getfloat(&x->x_xloc, ownertemplate, data, 1); + *xincp = fielddesc_getfloat(&x->x_xinc, ownertemplate, data, 1); + *ylocp = fielddesc_getfloat(&x->x_yloc, ownertemplate, data, 1); + *stylep = fielddesc_getfloat(&x->x_style, ownertemplate, data, 1); + *visp = fielddesc_getfloat(&x->x_vis, ownertemplate, data, 1); + *scalarvisp = fielddesc_getfloat(&x->x_scalarvis, ownertemplate, data, 1); + *elemtemplatesymp = elemtemplatesym; + *arrayp = array; + *xfield = &x->x_xpoints; + *yfield = &x->x_ypoints; + *wfield = &x->x_wpoints; + return (0); +} + + /* get everything else you could possibly need about a plot, + either for plot's own purposes or for plotting a "garray" */ +int array_getfields(t_symbol *elemtemplatesym, + t_canvas **elemtemplatecanvasp, + t_template **elemtemplatep, int *elemsizep, + t_fielddesc *xfielddesc, t_fielddesc *yfielddesc, t_fielddesc *wfielddesc, + int *xonsetp, int *yonsetp, int *wonsetp) +{ + int arrayonset, elemsize, yonset, wonset, xonset, type; + t_template *elemtemplate; + t_symbol *dummy, *varname; + t_canvas *elemtemplatecanvas = 0; + + /* the "float" template is special in not having to have a canvas; + template_findbyname is hardwired to return a predefined + template. */ + + if (!(elemtemplate = template_findbyname(elemtemplatesym))) + { + error("plot: %s: no such template", elemtemplatesym->s_name); + return (-1); + } + if (!((elemtemplatesym == &s_float) || + (elemtemplatecanvas = template_findcanvas(elemtemplate)))) + { + error("plot: %s: no canvas for this template", elemtemplatesym->s_name); + return (-1); + } + elemsize = elemtemplate->t_n * sizeof(t_word); + if (yfielddesc && yfielddesc->fd_var) + varname = yfielddesc->fd_un.fd_varsym; + else varname = gensym("y"); + if (!template_find_field(elemtemplate, varname, &yonset, &type, &dummy) + || type != DT_FLOAT) + yonset = -1; + if (xfielddesc && xfielddesc->fd_var) + varname = xfielddesc->fd_un.fd_varsym; + else varname = gensym("x"); + if (!template_find_field(elemtemplate, varname, &xonset, &type, &dummy) + || type != DT_FLOAT) + xonset = -1; + if (wfielddesc && wfielddesc->fd_var) + varname = wfielddesc->fd_un.fd_varsym; + else varname = gensym("w"); + if (!template_find_field(elemtemplate, varname, &wonset, &type, &dummy) + || type != DT_FLOAT) + wonset = -1; + + /* fill in slots for return values */ + *elemtemplatecanvasp = elemtemplatecanvas; + *elemtemplatep = elemtemplate; + *elemsizep = elemsize; + *xonsetp = xonset; + *yonsetp = yonset; + *wonsetp = wonset; + return (0); +} + +static void plot_getrect(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_plot *x = (t_plot *)z; + int elemsize, yonset, wonset, xonset; + t_canvas *elemtemplatecanvas; + t_template *elemtemplate; + t_symbol *elemtemplatesym; + t_float linewidth, xloc, xinc, yloc, style, xsum, yval, vis, scalarvis; + t_array *array; + int x1 = 0x7fffffff, y1 = 0x7fffffff, x2 = -0x7fffffff, y2 = -0x7fffffff; + int i; + t_float xpix, ypix, wpix; + t_fielddesc *xfielddesc, *yfielddesc, *wfielddesc; + /* if we're the only plot in the glist claim the whole thing */ + if (glist->gl_list && !glist->gl_list->g_next) + { + *xp1 = *yp1 = -0x7fffffff; + *xp2 = *yp2 = 0x7fffffff; + return; + } + if (!plot_readownertemplate(x, data, template, + &elemtemplatesym, &array, &linewidth, &xloc, &xinc, &yloc, &style, + &vis, &scalarvis, &xfielddesc, &yfielddesc, &wfielddesc) && + (vis != 0) && + !array_getfields(elemtemplatesym, &elemtemplatecanvas, + &elemtemplate, &elemsize, + xfielddesc, yfielddesc, wfielddesc, + &xonset, &yonset, &wonset)) + { + /* if it has more than 2000 points, just check 1000 of them. */ + int incr = (array->a_n <= 2000 ? 1 : array->a_n / 1000); + for (i = 0, xsum = 0; i < array->a_n; i += incr) + { + t_float usexloc, useyloc; + t_gobj *y; + /* get the coords of the point proper */ + array_getcoordinate(glist, (char *)(array->a_vec) + i * elemsize, + xonset, yonset, wonset, i, basex + xloc, basey + yloc, xinc, + xfielddesc, yfielddesc, wfielddesc, &xpix, &ypix, &wpix); + if (xpix < x1) + x1 = xpix; + if (xpix > x2) + x2 = xpix; + if (ypix - wpix < y1) + y1 = ypix - wpix; + if (ypix + wpix > y2) + y2 = ypix + wpix; + + if (scalarvis != 0) + { + /* check also the drawing instructions for the scalar */ + if (xonset >= 0) + usexloc = basex + xloc + fielddesc_cvttocoord(xfielddesc, + *(t_float *)(((char *)(array->a_vec) + elemsize * i) + + xonset)); + else usexloc = basex + xsum, xsum += xinc; + if (yonset >= 0) + yval = *(t_float *)(((char *)(array->a_vec) + elemsize * i) + + yonset); + else yval = 0; + useyloc = basey + yloc + fielddesc_cvttocoord(yfielddesc, yval); + for (y = elemtemplatecanvas->gl_list; y; y = y->g_next) + { + int xx1, xx2, yy1, yy2; + const t_parentwidgetbehavior *wb = + pd_getparentwidget(&y->g_pd); + if (!wb) continue; + (*wb->w_parentgetrectfn)(y, glist, + (t_word *)((char *)(array->a_vec) + elemsize * i), + elemtemplate, usexloc, useyloc, + &xx1, &yy1, &xx2, &yy2); + if (xx1 < x1) + x1 = xx1; + if (yy1 < y1) + y1 = yy1; + if (xx2 > x2) + x2 = xx2; + if (yy2 > y2) + y2 = yy2; + } + } + } + } + + *xp1 = x1; + *yp1 = y1; + *xp2 = x2; + *yp2 = y2; +} + +static void plot_displace(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int dx, int dy) +{ + /* not yet */ +} + +static void plot_select(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int state) +{ + /* not yet */ +} + +static void plot_activate(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int state) +{ + /* not yet */ +} + +#define CLIP(x) ((x) < 1e20 && (x) > -1e20 ? x : 0) + +static void plot_vis(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int tovis) +{ + t_plot *x = (t_plot *)z; + int elemsize, yonset, wonset, xonset, i; + t_canvas *elemtemplatecanvas; + t_template *elemtemplate; + t_symbol *elemtemplatesym; + t_float linewidth, xloc, xinc, yloc, style, usexloc, xsum, yval, vis, + scalarvis; + t_array *array; + int nelem; + char *elem; + t_fielddesc *xfielddesc, *yfielddesc, *wfielddesc; + /* even if the array is "invisible", if its visibility is + set by an instance variable you have to explicitly erase it, + because the flag could earlier have been on when we were getting + drawn. Rather than look to try to find out whether we're + visible we just do the erasure. At the TK level this should + cause no action because the tag matches nobody. LATER we + might want to optimize this somehow. Ditto the "vis()" routines + for other drawing instructions. */ + + if (plot_readownertemplate(x, data, template, + &elemtemplatesym, &array, &linewidth, &xloc, &xinc, &yloc, &style, + &vis, &scalarvis, &xfielddesc, &yfielddesc, &wfielddesc) || + ((vis == 0) && tovis) /* see above for 'tovis' */ + || array_getfields(elemtemplatesym, &elemtemplatecanvas, + &elemtemplate, &elemsize, xfielddesc, yfielddesc, wfielddesc, + &xonset, &yonset, &wonset)) + return; + nelem = array->a_n; + elem = (char *)array->a_vec; + + if (glist->gl_isgraph) + linewidth *= glist_getzoom(glist); + + if (tovis) + { + if (style == PLOTSTYLE_POINTS) + { + t_float minyval = 1e20, maxyval = -1e20; + int ndrawn = 0; + for (xsum = basex + xloc, i = 0; i < nelem; i++) + { + t_float yval, xpix, ypix, nextxloc; + int ixpix, inextx; + + if (xonset >= 0) + { + usexloc = basex + xloc + + *(t_float *)((elem + elemsize * i) + xonset); + ixpix = glist_xtopixels(glist, + fielddesc_cvttocoord(xfielddesc, usexloc)); + inextx = ixpix + 2; + } + else + { + usexloc = xsum; + xsum += xinc; + ixpix = glist_xtopixels(glist, + fielddesc_cvttocoord(xfielddesc, usexloc)); + inextx = glist_xtopixels(glist, + fielddesc_cvttocoord(xfielddesc, xsum)); + } + + if (yonset >= 0) + yval = yloc + *(t_float *)((elem + elemsize * i) + yonset); + else yval = 0; + yval = CLIP(yval); + if (yval < minyval) + minyval = yval; + if (yval > maxyval) + maxyval = yval; + if (i == nelem-1 || inextx != ixpix) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d " + "-fill black -width 0 -tags [list plot%lx array]\n", + glist_getcanvas(glist), + ixpix, (int)glist_ytopixels(glist, + basey + fielddesc_cvttocoord(yfielddesc, minyval)), + inextx, (int)(glist_ytopixels(glist, + basey + fielddesc_cvttocoord(yfielddesc, maxyval)) + + linewidth), data); + ndrawn++; + minyval = 1e20; + maxyval = -1e20; + } + if (ndrawn > 2000 || ixpix >= 3000) break; + } + } + else + { + char outline[20]; + int lastpixel = -1, ndrawn = 0; + t_float yval = 0, wval = 0, xpix; + int ixpix = 0; + /* draw the trace */ + numbertocolor(fielddesc_getfloat(&x->x_outlinecolor, template, + data, 1), outline); + if (wonset >= 0) + { + /* found "w" field which controls linewidth. The trace is + a filled polygon with 2n points. */ + sys_vgui(".x%lx.c create polygon \\\n", + glist_getcanvas(glist)); + + for (i = 0, xsum = xloc; i < nelem; i++) + { + if (xonset >= 0) + usexloc = xloc + *(t_float *)((elem + elemsize * i) + + xonset); + else usexloc = xsum, xsum += xinc; + if (yonset >= 0) + yval = *(t_float *)((elem + elemsize * i) + yonset); + else yval = 0; + yval = CLIP(yval); + wval = *(t_float *)((elem + elemsize * i) + wonset); + wval = CLIP(wval); + xpix = glist_xtopixels(glist, + basex + fielddesc_cvttocoord(xfielddesc, usexloc)); + ixpix = xpix + 0.5; + if (xonset >= 0 || ixpix != lastpixel) + { + sys_vgui("%d %f \\\n", ixpix, + glist_ytopixels(glist, + basey + fielddesc_cvttocoord(yfielddesc, + yloc + yval) - + fielddesc_cvttocoord(wfielddesc,wval))); + ndrawn++; + } + lastpixel = ixpix; + if (ndrawn >= 1000) goto ouch; + } + lastpixel = -1; + for (i = nelem-1; i >= 0; i--) + { + t_float usexloc; + if (xonset >= 0) + usexloc = xloc + *(t_float *)((elem + elemsize * i) + + xonset); + else xsum -= xinc, usexloc = xsum; + if (yonset >= 0) + yval = *(t_float *)((elem + elemsize * i) + yonset); + else yval = 0; + yval = CLIP(yval); + wval = *(t_float *)((elem + elemsize * i) + wonset); + wval = CLIP(wval); + xpix = glist_xtopixels(glist, + basex + fielddesc_cvttocoord(xfielddesc, usexloc)); + ixpix = xpix + 0.5; + if (xonset >= 0 || ixpix != lastpixel) + { + sys_vgui("%d %f \\\n", ixpix, glist_ytopixels(glist, + basey + yloc + fielddesc_cvttocoord(yfielddesc, + yval) + + fielddesc_cvttocoord(wfielddesc, wval))); + ndrawn++; + } + lastpixel = ixpix; + if (ndrawn >= 1000) goto ouch; + } + /* TK will complain if there aren't at least 3 points. + There should be at least two already. */ + if (ndrawn < 4) + { + sys_vgui("%d %f \\\n", ixpix + 10, glist_ytopixels(glist, + basey + yloc + fielddesc_cvttocoord(yfielddesc, + yval) + + fielddesc_cvttocoord(wfielddesc, wval))); + sys_vgui("%d %f \\\n", ixpix + 10, glist_ytopixels(glist, + basey + yloc + fielddesc_cvttocoord(yfielddesc, + yval) - + fielddesc_cvttocoord(wfielddesc, wval))); + } + ouch: + sys_vgui(" -width %d -fill %s -outline %s\\\n", + (glist->gl_isgraph ? glist_getzoom(glist) : 1), + outline, outline); + if (style == PLOTSTYLE_BEZ) sys_vgui("-smooth 1\\\n"); + + sys_vgui("-tags [list plot%lx array]\n", data); + } + else if (linewidth > 0) + { + /* no "w" field. If the linewidth is positive, draw a + segmented line with the requested width; otherwise don't + draw the trace at all. */ + sys_vgui(".x%lx.c create line \\\n", glist_getcanvas(glist)); + + for (xsum = xloc, i = 0; i < nelem; i++) + { + t_float usexloc; + if (xonset >= 0) + usexloc = xloc + *(t_float *)((elem + elemsize * i) + + xonset); + else usexloc = xsum, xsum += xinc; + if (yonset >= 0) + yval = *(t_float *)((elem + elemsize * i) + yonset); + else yval = 0; + yval = CLIP(yval); + xpix = glist_xtopixels(glist, + basex + fielddesc_cvttocoord(xfielddesc, usexloc)); + ixpix = xpix + 0.5; + if (xonset >= 0 || ixpix != lastpixel) + { + sys_vgui("%d %f \\\n", ixpix, + glist_ytopixels(glist, + basey + yloc + fielddesc_cvttocoord(yfielddesc, + yval))); + ndrawn++; + } + lastpixel = ixpix; + if (ndrawn >= 1000) break; + } + /* TK will complain if there aren't at least 2 points... */ + if (ndrawn == 0) sys_vgui("0 0 0 0 \\\n"); + else if (ndrawn == 1) sys_vgui("%d %f \\\n", ixpix + 10, + glist_ytopixels(glist, basey + yloc + + fielddesc_cvttocoord(yfielddesc, yval))); + + sys_vgui("-width %f\\\n", linewidth); + sys_vgui("-fill %s\\\n", outline); + if (style == PLOTSTYLE_BEZ) sys_vgui("-smooth 1\\\n"); + + sys_vgui("-tags [list plot%lx array]\n", data); + } + } + /* We're done with the outline; now draw all the points. + This code is inefficient since the template has to be + searched for drawing instructions for every last point. */ + if (scalarvis != 0) + { + for (xsum = xloc, i = 0; i < nelem; i++) + { + t_float usexloc, useyloc; + t_gobj *y; + if (xonset >= 0) + usexloc = basex + xloc + + *(t_float *)((elem + elemsize * i) + xonset); + else usexloc = basex + xsum, xsum += xinc; + if (yonset >= 0) + yval = *(t_float *)((elem + elemsize * i) + yonset); + else yval = 0; + useyloc = basey + yloc + + fielddesc_cvttocoord(yfielddesc, yval); + for (y = elemtemplatecanvas->gl_list; y; y = y->g_next) + { + const t_parentwidgetbehavior *wb = + pd_getparentwidget(&y->g_pd); + if (!wb) continue; + (*wb->w_parentvisfn)(y, glist, + (t_word *)(elem + elemsize * i), + elemtemplate, usexloc, useyloc, tovis); + } + } + } + } + else + { + /* un-draw the individual points */ + if (scalarvis != 0) + { + int i; + for (i = 0; i < nelem; i++) + { + t_gobj *y; + for (y = elemtemplatecanvas->gl_list; y; y = y->g_next) + { + const t_parentwidgetbehavior *wb = + pd_getparentwidget(&y->g_pd); + if (!wb) continue; + (*wb->w_parentvisfn)(y, glist, + (t_word *)(elem + elemsize * i), elemtemplate, + 0, 0, 0); + } + } + } + /* and then the trace */ + sys_vgui(".x%lx.c delete plot%lx\n", + glist_getcanvas(glist), data); + } +} + + /* LATER protect against the template changing or the scalar disappearing + probably by attaching a gpointer here ... */ + +static void array_motion(void *z, t_floatarg dx, t_floatarg dy) +{ + TEMPLATE->array_motion_xcumulative += dx * TEMPLATE->array_motion_xperpix; + TEMPLATE->array_motion_ycumulative += dy * TEMPLATE->array_motion_yperpix; + if (TEMPLATE->array_motion_xfield) + { + /* it's an x, y plot */ + int i; + for (i = 0; i < TEMPLATE->array_motion_npoints; i++) + { + t_word *thisword = (t_word *)(((char *)TEMPLATE->array_motion_wp) + + i * TEMPLATE->array_motion_elemsize); + t_float xwas = fielddesc_getcoord(TEMPLATE->array_motion_xfield, + TEMPLATE->array_motion_template, thisword, 1); + t_float ywas = (TEMPLATE->array_motion_yfield ? + fielddesc_getcoord(TEMPLATE->array_motion_yfield, + TEMPLATE->array_motion_template, thisword, 1) : 0); + fielddesc_setcoord(TEMPLATE->array_motion_xfield, + TEMPLATE->array_motion_template, thisword, xwas + dx, 1); + if (TEMPLATE->array_motion_yfield) + { + if (TEMPLATE->array_motion_fatten) + { + if (i == 0) + { + t_float newy = ywas + + dy * TEMPLATE->array_motion_yperpix; + if (newy < 0) + newy = 0; + fielddesc_setcoord(TEMPLATE->array_motion_yfield, + TEMPLATE->array_motion_template, thisword, newy, 1); + } + } + else + { + fielddesc_setcoord(TEMPLATE->array_motion_yfield, + TEMPLATE->array_motion_template, thisword, + ywas + dy * TEMPLATE->array_motion_yperpix, 1); + } + } + } + } + else if (TEMPLATE->array_motion_yfield) + { + /* a y-only plot. */ + int thisx = TEMPLATE->array_motion_initx + + TEMPLATE->array_motion_xcumulative + 0.5, x2; + int increment, i, nchange; + t_float newy = TEMPLATE->array_motion_ycumulative, + oldy = fielddesc_getcoord(TEMPLATE->array_motion_yfield, + TEMPLATE->array_motion_template, + (t_word *)(((char *)TEMPLATE->array_motion_wp) + + TEMPLATE->array_motion_elemsize * + TEMPLATE->array_motion_lastx), + 1); + t_float ydiff = newy - oldy; + if (thisx < 0) thisx = 0; + else if (thisx >= TEMPLATE->array_motion_npoints) + thisx = TEMPLATE->array_motion_npoints - 1; + increment = (thisx > TEMPLATE->array_motion_lastx ? -1 : 1); + nchange = 1 + increment * (TEMPLATE->array_motion_lastx - thisx); + + for (i = 0, x2 = thisx; i < nchange; i++, x2 += increment) + { + fielddesc_setcoord(TEMPLATE->array_motion_yfield, + TEMPLATE->array_motion_template, + (t_word *)(((char *)TEMPLATE->array_motion_wp) + + TEMPLATE->array_motion_elemsize * x2), newy, 1); + if (nchange > 1) + newy -= ydiff * (1./(nchange - 1)); + } + TEMPLATE->array_motion_lastx = thisx; + } + if (TEMPLATE->array_motion_scalar) + scalar_redraw(TEMPLATE->array_motion_scalar, + TEMPLATE->array_motion_glist); + if (TEMPLATE->array_motion_array) + array_redraw(TEMPLATE->array_motion_array, + TEMPLATE->array_motion_glist); +} + +int scalar_doclick(t_word *data, t_template *template, t_scalar *sc, + t_array *ap, struct _glist *owner, + t_float xloc, t_float yloc, int xpix, int ypix, + int shift, int alt, int dbl, int doit); + + /* try clicking on an element of the array as a scalar (if clicking + on the trace of the array failed) */ +static int array_doclick_element(t_array *array, t_glist *glist, + t_scalar *sc, t_array *ap, + t_symbol *elemtemplatesym, + t_float linewidth, t_float xloc, t_float xinc, t_float yloc, + t_fielddesc *xfield, t_fielddesc *yfield, t_fielddesc *wfield, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_canvas *elemtemplatecanvas; + t_template *elemtemplate; + int elemsize, yonset, wonset, xonset, i, incr, hit; + t_float xsum; + + if (elemtemplatesym == &s_float) + return (0); + if (array_getfields(elemtemplatesym, &elemtemplatecanvas, + &elemtemplate, &elemsize, xfield, yfield, wfield, + &xonset, &yonset, &wonset)) + return (0); + /* if it has more than 2000 points, just check 300 of them. */ + if (array->a_n < 2000) + incr = 1; + else incr = array->a_n / 300; + for (i = 0, xsum = 0; i < array->a_n; i += incr) + { + t_float usexloc, useyloc; + if (xonset >= 0) + usexloc = xloc + fielddesc_cvttocoord(xfield, + *(t_float *)(((char *)(array->a_vec) + elemsize * i) + xonset)); + else usexloc = xloc + xsum, xsum += xinc; + useyloc = yloc + (yonset >= 0 ? fielddesc_cvttocoord(yfield, + *(t_float *) + (((char *)(array->a_vec) + elemsize * i) + yonset)) : 0); + + if ((hit = scalar_doclick( + (t_word *)((char *)(array->a_vec) + i * elemsize), + elemtemplate, 0, array, + glist, usexloc, useyloc, + xpix, ypix, shift, alt, dbl, doit))) + return (hit); + } + return (0); +} + +static int array_doclick(t_array *array, t_glist *glist, t_scalar *sc, + t_array *ap, t_symbol *elemtemplatesym, + t_float linewidth, t_float xloc, t_float xinc, t_float yloc, + t_float scalarvis, + t_fielddesc *xfield, t_fielddesc *yfield, t_fielddesc *wfield, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_canvas *elemtemplatecanvas; + t_template *elemtemplate; + int elemsize, yonset, wonset, xonset, i, callmotion = 0; + + if (!array_getfields(elemtemplatesym, &elemtemplatecanvas, + &elemtemplate, &elemsize, xfield, yfield, wfield, + &xonset, &yonset, &wonset)) + { + t_float best = 100; + /* if it has more than 2000 points, just check 1000 of them. */ + int incr = (array->a_n <= 2000 ? 1 : array->a_n / 1000); + TEMPLATE->array_motion_elemsize = elemsize; + TEMPLATE->array_motion_glist = glist; + TEMPLATE->array_motion_scalar = sc; + TEMPLATE->array_motion_array = ap; + TEMPLATE->array_motion_template = elemtemplate; + TEMPLATE->array_motion_xperpix = glist_dpixtodx(glist, 1); + TEMPLATE->array_motion_yperpix = glist_dpixtody(glist, 1); + /* if we're a garray, the only one here, and if we appear to have + only a 'y' field, click always succeeds and furthermore we'll + call "motion" later. */ + if (glist->gl_list && pd_class(&glist->gl_list->g_pd) == garray_class + && !glist->gl_list->g_next && + elemsize == sizeof(t_word)) + { + int xval = glist_pixelstox(glist, xpix); + if (xval < 0) + xval = 0; + else if (xval >= array->a_n) + xval = array->a_n - 1; + TEMPLATE->array_motion_yfield = yfield; + TEMPLATE->array_motion_ycumulative = glist_pixelstoy(glist, ypix); + TEMPLATE->array_motion_fatten = 0; + TEMPLATE->array_motion_xfield = 0; + TEMPLATE->array_motion_xcumulative = 0; + TEMPLATE->array_motion_lastx = TEMPLATE->array_motion_initx = xval; + TEMPLATE->array_motion_npoints = array->a_n; + TEMPLATE->array_motion_wp = (t_word *)((char *)array->a_vec); + if (doit) + { + fielddesc_setcoord(yfield, elemtemplate, + (t_word *)(((char *)array->a_vec) + elemsize * xval), + glist_pixelstoy(glist, ypix), 1); + glist_grab(glist, 0, array_motion, 0, xpix, ypix); + if (TEMPLATE->array_motion_scalar) + scalar_redraw(TEMPLATE->array_motion_scalar, + TEMPLATE->array_motion_glist); + if (TEMPLATE->array_motion_array) + array_redraw(TEMPLATE->array_motion_array, + TEMPLATE->array_motion_glist); + } + } + else + { + for (i = 0; i < array->a_n; i += incr) + { + t_float pxpix, pypix, pwpix, dx, dy; + array_getcoordinate(glist, + (char *)(array->a_vec) + i * elemsize, + xonset, yonset, wonset, i, xloc, yloc, xinc, + xfield, yfield, wfield, &pxpix, &pypix, &pwpix); + if (pwpix < 4) + pwpix = 4; + dx = pxpix - xpix; + if (dx < 0) dx = -dx; + if (dx > 8) + continue; + dy = pypix - ypix; + if (dy < 0) dy = -dy; + if (dx + dy < best) + best = dx + dy; + if (wonset >= 0) + { + dy = (pypix + pwpix) - ypix; + if (dy < 0) dy = -dy; + if (dx + dy < best) + best = dx + dy; + dy = (pypix - pwpix) - ypix; + if (dy < 0) dy = -dy; + if (dx + dy < best) + best = dx + dy; + } + } + if (best > 8) + { + if (scalarvis != 0) + return (array_doclick_element(array, glist, sc, ap, + elemtemplatesym, linewidth, xloc, xinc, yloc, + xfield, yfield, wfield, + xpix, ypix, shift, alt, dbl, doit)); + else return (0); + } + best += 0.001; /* add truncation error margin */ + for (i = 0; i < array->a_n; i += incr) + { + t_float pxpix, pypix, pwpix, dx, dy, dy2, dy3; + array_getcoordinate(glist, + (char *)(array->a_vec) + i * elemsize, + xonset, yonset, wonset, i, xloc, yloc, xinc, + xfield, yfield, wfield, &pxpix, &pypix, &pwpix); + if (pwpix < 4) + pwpix = 4; + dx = pxpix - xpix; + if (dx < 0) dx = -dx; + dy = pypix - ypix; + if (dy < 0) dy = -dy; + if (wonset >= 0) + { + dy2 = (pypix + pwpix) - ypix; + if (dy2 < 0) dy2 = -dy2; + dy3 = (pypix - pwpix) - ypix; + if (dy3 < 0) dy3 = -dy3; + if (yonset < 0) + dy = 100; + } + else dy2 = dy3 = 100; + if (dx + dy <= best || dx + dy2 <= best || dx + dy3 <= best) + { + if (dy < dy2 && dy < dy3) + TEMPLATE->array_motion_fatten = 0; + else if (dy2 < dy3) + TEMPLATE->array_motion_fatten = -1; + else TEMPLATE->array_motion_fatten = 1; + if (doit) + { + char *elem = (char *)array->a_vec; + if (alt && xpix < pxpix) /* delete a point */ + { + if (array->a_n <= 1) + return (0); + memmove((char *)(array->a_vec) + elemsize * i, + (char *)(array->a_vec) + elemsize * (i+1), + (array->a_n - 1 - i) * elemsize); + array_resize_and_redraw(array, + glist, array->a_n - 1); + return (0); + } + else if (alt) + { + /* add a point (after the clicked-on one) */ + array_resize_and_redraw(array, glist, + array->a_n + 1); + elem = (char *)array->a_vec; + memmove(elem + elemsize * (i+1), + elem + elemsize * i, + (array->a_n - i - 1) * elemsize); + i++; + } + if (xonset >= 0) + { + TEMPLATE->array_motion_xfield = xfield; + TEMPLATE->array_motion_xcumulative = + fielddesc_getcoord(xfield, + TEMPLATE->array_motion_template, + (t_word *)(elem + i * elemsize), 1); + TEMPLATE->array_motion_wp = + (t_word *)(elem + i * elemsize); + if (shift) + TEMPLATE->array_motion_npoints = + array->a_n - i; + else TEMPLATE->array_motion_npoints = 1; + } + else + { + TEMPLATE->array_motion_xfield = 0; + TEMPLATE->array_motion_xcumulative = 0; + TEMPLATE->array_motion_wp = (t_word *)elem; + TEMPLATE->array_motion_npoints = array->a_n; + + TEMPLATE->array_motion_initx = i; + TEMPLATE->array_motion_lastx = i; + TEMPLATE->array_motion_xperpix *= + (xinc == 0 ? 1 : 1./xinc); + } + if (TEMPLATE->array_motion_fatten) + { + TEMPLATE->array_motion_yfield = wfield; + TEMPLATE->array_motion_ycumulative = + fielddesc_getcoord(wfield, + TEMPLATE->array_motion_template, + (t_word *)(elem + i * elemsize), 1); + TEMPLATE->array_motion_yperpix *= + -TEMPLATE->array_motion_fatten; + } + else if (yonset >= 0) + { + TEMPLATE->array_motion_yfield = yfield; + TEMPLATE->array_motion_ycumulative = + fielddesc_getcoord(yfield, + TEMPLATE->array_motion_template, + (t_word *)(elem + i * elemsize), 1); + } + else + { + TEMPLATE->array_motion_yfield = 0; + TEMPLATE->array_motion_ycumulative = 0; + } + glist_grab(glist, 0, array_motion, 0, xpix, ypix); + } + if (alt) + { + if (xpix < pxpix) + return (CURSOR_EDITMODE_DISCONNECT); + else return (CURSOR_RUNMODE_ADDPOINT); + } + else return (TEMPLATE->array_motion_fatten ? + CURSOR_RUNMODE_THICKEN : CURSOR_RUNMODE_CLICKME); + } + } + } + } + return (0); +} + +static int plot_click(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_scalar *sc, t_array *ap, + t_float basex, t_float basey, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_plot *x = (t_plot *)z; + t_symbol *elemtemplatesym; + t_float linewidth, xloc, xinc, yloc, style, vis, scalarvis; + t_array *array; + t_fielddesc *xfielddesc, *yfielddesc, *wfielddesc; + + if (!plot_readownertemplate(x, data, template, + &elemtemplatesym, &array, &linewidth, &xloc, &xinc, &yloc, &style, + &vis, &scalarvis, + &xfielddesc, &yfielddesc, &wfielddesc) && (vis != 0)) + { + return (array_doclick(array, glist, sc, ap, + elemtemplatesym, + linewidth, basex + xloc, xinc, basey + yloc, scalarvis, + xfielddesc, yfielddesc, wfielddesc, + xpix, ypix, shift, alt, dbl, doit)); + } + else return (0); +} + +const t_parentwidgetbehavior plot_widgetbehavior = +{ + plot_getrect, + plot_displace, + plot_select, + plot_activate, + plot_vis, + plot_click, +}; + +static void plot_setup(void) +{ + plot_class = class_new(gensym("plot"), (t_newmethod)plot_new, 0, + sizeof(t_plot), 0, A_GIMME, 0); + class_setdrawcommand(plot_class); + class_addfloat(plot_class, plot_float); + class_setparentwidget(plot_class, &plot_widgetbehavior); +} + +/* ---------------- drawnumber: draw a number (or symbol) ---------------- */ + +/* + drawnumbers draw numeric fields at controllable locations, with + controllable color and label. invocation: + (drawnumber|drawsymbol) [-v ] variable x y color label +*/ + +t_class *drawnumber_class; + +typedef struct _drawnumber +{ + t_object x_obj; + t_symbol *x_fieldname; + t_fielddesc x_xloc; + t_fielddesc x_yloc; + t_fielddesc x_color; + t_fielddesc x_vis; + t_symbol *x_label; + t_canvas *x_canvas; +} t_drawnumber; + +static void *drawnumber_new(t_symbol *classsym, int argc, t_atom *argv) +{ + t_drawnumber *x = (t_drawnumber *)pd_new(drawnumber_class); + char *classname = classsym->s_name; + + fielddesc_setfloat_const(&x->x_vis, 1); + x->x_canvas = canvas_getcurrent(); + while (1) + { + t_symbol *firstarg = atom_getsymbolarg(0, argc, argv); + if (!strcmp(firstarg->s_name, "-v") && argc > 1) + { + fielddesc_setfloatarg(&x->x_vis, 1, argv+1); + argc -= 2; argv += 2; + } + else break; + } + /* next argument is name of field to draw - we don't know its type yet + but fielddesc_setfloatarg() will do fine here. */ + x->x_fieldname = atom_getsymbolarg(0, argc, argv); + if (argc) + argc--, argv++; + if (argc) fielddesc_setfloatarg(&x->x_xloc, argc--, argv++); + else fielddesc_setfloat_const(&x->x_xloc, 0); + if (argc) fielddesc_setfloatarg(&x->x_yloc, argc--, argv++); + else fielddesc_setfloat_const(&x->x_yloc, 0); + if (argc) fielddesc_setfloatarg(&x->x_color, argc--, argv++); + else fielddesc_setfloat_const(&x->x_color, 1); + if (argc) + x->x_label = atom_getsymbolarg(0, argc, argv); + else x->x_label = &s_; + + return (x); +} + +void drawnumber_float(t_drawnumber *x, t_floatarg f) +{ + int viswas; + if (x->x_vis.fd_type != A_FLOAT || x->x_vis.fd_var) + { + pd_error(x, "global vis/invis for a template with variable visibility"); + return; + } + viswas = (x->x_vis.fd_un.fd_float != 0); + + if ((f != 0 && viswas) || (f == 0 && !viswas)) + return; + canvas_redrawallfortemplatecanvas(x->x_canvas, 2); + fielddesc_setfloat_const(&x->x_vis, (f != 0)); + canvas_redrawallfortemplatecanvas(x->x_canvas, 1); +} + +/* -------------------- widget behavior for drawnumber ------------ */ + +static int drawnumber_gettype(t_drawnumber *x, t_word *data, + t_template *template, int *onsetp) +{ + int type; + t_symbol *arraytype; + if (template_find_field(template, x->x_fieldname, onsetp, &type, + &arraytype) && type != DT_ARRAY) + return (type); + else return (-1); +} + +#define DRAWNUMBER_BUFSIZE 1024 +static void drawnumber_getbuf(t_drawnumber *x, t_word *data, + t_template *template, char *buf) +{ + int nchars, onset, type = drawnumber_gettype(x, data, template, &onset); + if (type < 0) + buf[0] = 0; + else + { + strncpy(buf, x->x_label->s_name, DRAWNUMBER_BUFSIZE); + buf[DRAWNUMBER_BUFSIZE - 1] = 0; + nchars = (int)strlen(buf); + if (type == DT_TEXT) + { + char *buf2; + int size2, ncopy; + binbuf_gettext(((t_word *)((char *)data + onset))->w_binbuf, + &buf2, &size2); + ncopy = (size2 > DRAWNUMBER_BUFSIZE-1-nchars ? + DRAWNUMBER_BUFSIZE-1-nchars: size2); + memcpy(buf+nchars, buf2, ncopy); + buf[nchars+ncopy] = 0; + if (nchars+ncopy == DRAWNUMBER_BUFSIZE-1) + strcpy(buf+(DRAWNUMBER_BUFSIZE-4), "..."); + t_freebytes(buf2, size2); + } + else + { + t_atom at; + if (type == DT_FLOAT) + SETFLOAT(&at, ((t_word *)((char *)data + onset))->w_float); + else SETSYMBOL(&at, ((t_word *)((char *)data + onset))->w_symbol); + atom_string(&at, buf + nchars, DRAWNUMBER_BUFSIZE - nchars); + } + } +} + +static void drawnumber_getrect(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_drawnumber *x = (t_drawnumber *)z; + t_atom at; + int xloc, yloc, fontwidth, fontheight, bufsize, width, height; + char buf[DRAWNUMBER_BUFSIZE], *startline, *newline; + + if (!fielddesc_getfloat(&x->x_vis, template, data, 0)) + { + *xp1 = *yp1 = 0x7fffffff; + *xp2 = *yp2 = -0x7fffffff; + return; + } + xloc = glist_xtopixels(glist, + basex + fielddesc_getcoord(&x->x_xloc, template, data, 0)); + yloc = glist_ytopixels(glist, + basey + fielddesc_getcoord(&x->x_yloc, template, data, 0)); + fontwidth = glist_fontwidth(glist); + fontheight = glist_fontheight(glist); + drawnumber_getbuf(x, data, template, buf); + width = 0; + height = 1; + for (startline = buf; (newline = strchr(startline, '\n')); + startline = newline+1) + { + if (newline - startline > width) + width = (int)(newline - startline); + height++; + } + if (strlen(startline) > (unsigned)width) + width = (int)strlen(startline); + *xp1 = xloc; + *yp1 = yloc; + *xp2 = xloc + fontwidth * width; + *yp2 = yloc + fontheight * height; +} + +static void drawnumber_displace(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int dx, int dy) +{ + /* refuse */ +} + +static void drawnumber_select(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int state) +{ + post("drawnumber_select %d", state); + /* fill in later */ +} + +static void drawnumber_activate(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int state) +{ + post("drawnumber_activate %d", state); +} + +static void drawnumber_vis(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_float basex, t_float basey, + int vis) +{ + t_drawnumber *x = (t_drawnumber *)z; + + /* see comment in plot_vis() */ + if (vis && !fielddesc_getfloat(&x->x_vis, template, data, 0)) + return; + if (vis) + { + t_atom at; + int xloc = glist_xtopixels(glist, + basex + fielddesc_getcoord(&x->x_xloc, template, data, 0)); + int yloc = glist_ytopixels(glist, + basey + fielddesc_getcoord(&x->x_yloc, template, data, 0)); + char colorstring[20], buf[DRAWNUMBER_BUFSIZE]; + numbertocolor(fielddesc_getfloat(&x->x_color, template, data, 1), + colorstring); + drawnumber_getbuf(x, data, template, buf); + sys_vgui(".x%lx.c create text %d %d -anchor nw -fill %s -text {%s}", + glist_getcanvas(glist), xloc, yloc, colorstring, buf); + sys_vgui(" -font {{%s} -%d %s}", sys_font, + sys_hostfontsize(glist_getfont(glist), 1), + sys_fontweight); + sys_vgui(" -tags [list drawnumber%lx label]\n", data); + } + else sys_vgui(".x%lx.c delete drawnumber%lx\n", + glist_getcanvas(glist), data); +} + +static void drawnumber_motion(void *z, t_floatarg dx, t_floatarg dy) +{ + t_drawnumber *x = (t_drawnumber *)z; + t_atom at; + if (!gpointer_check(&TEMPLATE->drawnumber_motion_gpointer, 0)) + { + post("drawnumber_motion: scalar disappeared"); + return; + } + if (TEMPLATE->drawnumber_motion_type != DT_FLOAT) + return; + TEMPLATE->drawnumber_motion_ycumulative -= dy; + template_setfloat(TEMPLATE->drawnumber_motion_template, + x->x_fieldname, + TEMPLATE->drawnumber_motion_wp, + TEMPLATE->drawnumber_motion_ycumulative, + 1); + if (TEMPLATE->drawnumber_motion_scalar) + template_notifyforscalar(TEMPLATE->drawnumber_motion_template, + TEMPLATE->drawnumber_motion_glist, + TEMPLATE->drawnumber_motion_scalar, + gensym("change"), 1, &at); + + if (TEMPLATE->drawnumber_motion_scalar) + scalar_redraw(TEMPLATE->drawnumber_motion_scalar, + TEMPLATE->drawnumber_motion_glist); + if (TEMPLATE->drawnumber_motion_array) + array_redraw(TEMPLATE->drawnumber_motion_array, + TEMPLATE->drawnumber_motion_glist); +} + +static void drawnumber_key(void *z, t_floatarg fkey) +{ + t_drawnumber *x = (t_drawnumber *)z; + int key = fkey; + char sbuf[MAXPDSTRING]; + t_atom at; + if (!gpointer_check(&TEMPLATE->drawnumber_motion_gpointer, 0)) + { + post("drawnumber_motion: scalar disappeared"); + return; + } + if (key == 0) + return; + if (TEMPLATE->drawnumber_motion_type == DT_SYMBOL) + { + /* key entry for a symbol field */ + if (TEMPLATE->drawnumber_motion_firstkey) + sbuf[0] = 0; + else strncpy(sbuf, + template_getsymbol(TEMPLATE->drawnumber_motion_template, + x->x_fieldname, TEMPLATE->drawnumber_motion_wp, 1)->s_name, + MAXPDSTRING); + sbuf[MAXPDSTRING-1] = 0; + if (key == '\b') + { + if (*sbuf) + sbuf[strlen(sbuf)-1] = 0; + } + else + { + sbuf[strlen(sbuf)+1] = 0; + sbuf[strlen(sbuf)] = key; + } + } + else if (TEMPLATE->drawnumber_motion_type == DT_FLOAT) + { + /* key entry for a numeric field. This is just a stopgap. */ + double newf; + if (TEMPLATE->drawnumber_motion_firstkey) + sbuf[0] = 0; + else sprintf(sbuf, "%g", + template_getfloat(TEMPLATE->drawnumber_motion_template, + x->x_fieldname, TEMPLATE->drawnumber_motion_wp, 1)); + TEMPLATE->drawnumber_motion_firstkey = (key == '\n'); + if (key == '\b') + { + if (*sbuf) + sbuf[strlen(sbuf)-1] = 0; + } + else + { + sbuf[strlen(sbuf)+1] = 0; + sbuf[strlen(sbuf)] = key; + } + if (sscanf(sbuf, "%lg", &newf) < 1) + newf = 0; + template_setfloat(TEMPLATE->drawnumber_motion_template, + x->x_fieldname, TEMPLATE->drawnumber_motion_wp, (t_float)newf, 1); + if (TEMPLATE->drawnumber_motion_scalar) + template_notifyforscalar(TEMPLATE->drawnumber_motion_template, + TEMPLATE->drawnumber_motion_glist, + TEMPLATE->drawnumber_motion_scalar, + gensym("change"), 1, &at); + if (TEMPLATE->drawnumber_motion_scalar) + scalar_redraw(TEMPLATE->drawnumber_motion_scalar, + TEMPLATE->drawnumber_motion_glist); + if (TEMPLATE->drawnumber_motion_array) + array_redraw(TEMPLATE->drawnumber_motion_array, + TEMPLATE->drawnumber_motion_glist); + } + else post("typing at text fields not yet implemented"); +} + +static int drawnumber_click(t_gobj *z, t_glist *glist, + t_word *data, t_template *template, t_scalar *sc, t_array *ap, + t_float basex, t_float basey, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_drawnumber *x = (t_drawnumber *)z; + int x1, y1, x2, y2, type, onset; + drawnumber_getrect(z, glist, + data, template, basex, basey, + &x1, &y1, &x2, &y2); + if (xpix >= x1 && xpix <= x2 && ypix >= y1 && ypix <= y2 && + ((type = drawnumber_gettype(x, data, template, &onset)) == DT_FLOAT || + type == DT_SYMBOL)) + { + if (doit) + { + TEMPLATE->drawnumber_motion_glist = glist; + TEMPLATE->drawnumber_motion_wp = data; + TEMPLATE->drawnumber_motion_template = template; + TEMPLATE->drawnumber_motion_scalar = sc; + TEMPLATE->drawnumber_motion_array = ap; + TEMPLATE->drawnumber_motion_firstkey = 1; + TEMPLATE->drawnumber_motion_ycumulative = + template_getfloat(template, x->x_fieldname, data, 0); + TEMPLATE->drawnumber_motion_type = type; + if (TEMPLATE->drawnumber_motion_scalar) + gpointer_setglist(&TEMPLATE->drawnumber_motion_gpointer, + TEMPLATE->drawnumber_motion_glist, + TEMPLATE->drawnumber_motion_scalar); + else gpointer_setarray(&TEMPLATE->drawnumber_motion_gpointer, + TEMPLATE->drawnumber_motion_array, + TEMPLATE->drawnumber_motion_wp); + glist_grab(glist, z, drawnumber_motion, drawnumber_key, + xpix, ypix); + } + return (1); + } + else return (0); +} + +const t_parentwidgetbehavior drawnumber_widgetbehavior = +{ + drawnumber_getrect, + drawnumber_displace, + drawnumber_select, + drawnumber_activate, + drawnumber_vis, + drawnumber_click, +}; + +static void drawnumber_free(t_drawnumber *x) +{ +} + +static void drawnumber_setup(void) +{ + drawnumber_class = class_new(gensym("drawtext"), + (t_newmethod)drawnumber_new, (t_method)drawnumber_free, + sizeof(t_drawnumber), 0, A_GIMME, 0); + class_setdrawcommand(drawnumber_class); + class_addfloat(drawnumber_class, drawnumber_float); + class_addcreator((t_newmethod)drawnumber_new, gensym("drawsymbol"), + A_GIMME, 0); + class_addcreator((t_newmethod)drawnumber_new, gensym("drawnumber"), + A_GIMME, 0); + class_setparentwidget(drawnumber_class, &drawnumber_widgetbehavior); +} + +/* ---------------------- setup function ---------------------------- */ + +void g_template_setup(void) +{ + template_setup(); + gtemplate_setup(); + curve_setup(); + plot_setup(); + drawnumber_setup(); +} + +void g_template_newpdinstance( void) +{ + TEMPLATE = getbytes(sizeof(*TEMPLATE)); +} + +void g_template_freepdinstance( void) +{ + freebytes(TEMPLATE, sizeof(*TEMPLATE)); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_text.c b/ports/camomile/source/LibPd/pure-data/src/g_text.c new file mode 100644 index 00000000..b5d44874 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_text.c @@ -0,0 +1,1489 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* changes by Thomas Musil IEM KUG Graz Austria 2001 */ +/* the methods for calling the gui-objects from menu are implemented */ +/* all changes are labeled with iemlib */ + +#include +#include "m_pd.h" +#include "m_imp.h" +#include "s_stuff.h" + +#include "g_canvas.h" +#include +#include +#include + +#include "s_utf8.h" + +/* borrowed from RMARGIN and BMARGIN in g_rtext.c */ +#define ATOM_RMARGIN 2 +#define ATOM_BMARGIN 4 /* 1 pixel smaller than object TMARGIN+BMARGIN */ + +#define MESSAGE_CLICK_WIDTH 5 + +t_class *text_class; +static t_class *message_class; +static t_class *gatom_class; +static void text_vis(t_gobj *z, t_glist *glist, int vis); +static void text_displace(t_gobj *z, t_glist *glist, + int dx, int dy); +static void text_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2); + +void canvas_startmotion(t_canvas *x); + +/* ----------------- the "text" object. ------------------ */ + + /* add a "text" object (comment) to a glist. While this one goes for any + glist, the other 3 below are for canvases only. (why?) This is called + without args if invoked from the GUI; otherwise at least x and y + are provided. */ + +void glist_text(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + t_text *x = (t_text *)pd_new(text_class); + t_atom at; + x->te_width = 0; /* don't know it yet. */ + x->te_type = T_TEXT; + x->te_binbuf = binbuf_new(); + if (argc > 1) + { + x->te_xpix = atom_getfloatarg(0, argc, argv); + x->te_ypix = atom_getfloatarg(1, argc, argv); + if (argc > 2) binbuf_restore(x->te_binbuf, argc-2, argv+2); + else + { + SETSYMBOL(&at, gensym("comment")); + binbuf_restore(x->te_binbuf, 1, &at); + } + glist_add(gl, &x->te_g); + } + else + { + int xpix, ypix; + pd_vmess((t_pd *)glist_getcanvas(gl), gensym("editmode"), "i", 1); + SETSYMBOL(&at, gensym("comment")); + glist_noselect(gl); + glist_getnextxy(gl, &xpix, &ypix); + x->te_xpix = xpix-1; + x->te_ypix = ypix-1; + binbuf_restore(x->te_binbuf, 1, &at); + glist_add(gl, &x->te_g); + glist_noselect(gl); + glist_select(gl, &x->te_g); + /* it would be nice to "activate" here, but then the second, + "put-me-down" click changes the text selection, which is quite + irritating, so I took this back out. It's OK in messages + and objects though since there's no text in them at menu + creation. */ + /* gobj_activate(&x->te_g, gl, 1); */ + canvas_startmotion(glist_getcanvas(gl)); + } +} + +/* ----------------- the "object" object. ------------------ */ + +void canvas_getargs(int *argcp, t_atom **argvp); + +static void canvas_objtext(t_glist *gl, int xpix, int ypix, int width, + int selected, t_binbuf *b) +{ + t_text *x; + int argc; + t_atom *argv; + pd_this->pd_newest = 0; + canvas_setcurrent((t_canvas *)gl); + canvas_getargs(&argc, &argv); + binbuf_eval(b, &pd_objectmaker, argc, argv); + if (binbuf_getnatom(b)) + { + if (!pd_this->pd_newest) + x = 0; + else if (!(x = pd_checkobject(pd_this->pd_newest))) + { + binbuf_print(b); + error("... didn't return a patchable object"); + } + } + else x = 0; + if (!x) + { + x = (t_text *)pd_new(text_class); + if (binbuf_getnatom(b)) + { + binbuf_print(b); + pd_error(x, "... couldn't create"); + } + } + x->te_binbuf = b; + x->te_xpix = xpix; + x->te_ypix = ypix; + x->te_width = width; + x->te_type = T_OBJECT; + glist_add(gl, &x->te_g); + if (selected) + { + /* this is called if we've been created from the menu. */ + glist_select(gl, &x->te_g); + gobj_activate(&x->te_g, gl, 1); + } + if (pd_class(&x->ob_pd) == vinlet_class) + canvas_resortinlets(glist_getcanvas(gl)); + if (pd_class(&x->ob_pd) == voutlet_class) + canvas_resortoutlets(glist_getcanvas(gl)); + canvas_unsetcurrent((t_canvas *)gl); +} + +extern int sys_noautopatch; + /* utility routine to figure out where to put a new text box from menu + and whether to connect to it automatically */ +static void canvas_howputnew(t_canvas *x, int *connectp, int *xpixp, int *ypixp, + int *indexp, int *totalp) +{ + int xpix, ypix, indx = 0, nobj = 0, n2, x1, x2, y1, y2; + int connectme = (x->gl_editor->e_selection && + !x->gl_editor->e_selection->sel_next && !sys_noautopatch); + if (connectme) + { + t_gobj *g, *selected = x->gl_editor->e_selection->sel_what; + for (g = x->gl_list, nobj = 0; g; g = g->g_next, nobj++) + if (g == selected) + { + gobj_getrect(g, x, &x1, &y1, &x2, &y2); + indx = nobj; + *xpixp = x1; + *ypixp = y2 + 5; + } + glist_noselect(x); + /* search back for 'selected' and if it isn't on the list, + plan just to connect from the last item on the list. */ + for (g = x->gl_list, n2 = 0; g; g = g->g_next, n2++) + { + if (g == selected) + { + indx = n2; + break; + } + else if (!g->g_next) + indx = nobj-1; + } + } + else + { + glist_getnextxy(x, xpixp, ypixp); + *xpixp -= 3; + *ypixp -= 3; + glist_noselect(x); + } + *connectp = connectme; + *indexp = indx; + *totalp = nobj; +} + + /* object creation routine. These are called without any arguments if + they're invoked from the gui; when pasting or restoring from a file, we + get at least x and y. */ + +void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + t_text *x; + if (argc >= 2) + { + t_binbuf *b = binbuf_new(); + binbuf_restore(b, argc-2, argv+2); + canvas_objtext(gl, atom_getfloatarg(0, argc, argv), + atom_getfloatarg(1, argc, argv), 0, 0, b); + } + /* JMZ: don't go into interactive mode in a closed canvas */ + else if (!glist_isvisible(gl)) + post("unable to create stub object in closed canvas!"); + else + { + /* interactively create new obect */ + t_binbuf *b = binbuf_new(); + int connectme, xpix, ypix, indx, nobj; + canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj); + pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1); + canvas_objtext(gl, xpix, ypix, 0, 1, b); + if (connectme) + canvas_connect(gl, indx, 0, nobj, 0); + else canvas_startmotion(glist_getcanvas(gl)); + } +} + +/* make an object box for an object that's already there. */ + +/* iemlib */ +void canvas_iemguis(t_glist *gl, t_symbol *guiobjname) +{ + t_atom at; + t_binbuf *b = binbuf_new(); + int xpix, ypix; + + pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1); + glist_noselect(gl); + SETSYMBOL(&at, guiobjname); + binbuf_restore(b, 1, &at); + glist_getnextxy(gl, &xpix, &ypix); + canvas_objtext(gl, xpix, ypix, 0, 1, b); + canvas_startmotion(glist_getcanvas(gl)); +} + +void canvas_bng(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_iemguis(gl, gensym("bng")); +} + +void canvas_toggle(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_iemguis(gl, gensym("tgl")); +} + +void canvas_vslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_iemguis(gl, gensym("vsl")); +} + +void canvas_hslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_iemguis(gl, gensym("hsl")); +} + +void canvas_hdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_iemguis(gl, gensym("hdl")); +} + +void canvas_vdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_iemguis(gl, gensym("vdl")); +} + +void canvas_hradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_iemguis(gl, gensym("hradio")); +} + +void canvas_vradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_iemguis(gl, gensym("vradio")); +} + +void canvas_vumeter(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_iemguis(gl, gensym("vu")); +} + +void canvas_mycnv(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_iemguis(gl, gensym("cnv")); +} + +void canvas_numbox(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_iemguis(gl, gensym("nbx")); +} + +/* iemlib */ + +void canvas_objfor(t_glist *gl, t_text *x, int argc, t_atom *argv) +{ + x->te_width = 0; /* don't know it yet. */ + x->te_type = T_OBJECT; + x->te_binbuf = binbuf_new(); + x->te_xpix = atom_getfloatarg(0, argc, argv); + x->te_ypix = atom_getfloatarg(1, argc, argv); + if (argc > 2) binbuf_restore(x->te_binbuf, argc-2, argv+2); + glist_add(gl, &x->te_g); +} + +/* ---------------------- the "message" text item ------------------------ */ + +typedef struct _messresponder +{ + t_pd mr_pd; + t_outlet *mr_outlet; +} t_messresponder; + +typedef struct _message +{ + t_text m_text; + t_messresponder m_messresponder; + t_glist *m_glist; + t_clock *m_clock; +} t_message; + +static t_class *message_class, *messresponder_class; + +static void messresponder_bang(t_messresponder *x) +{ + outlet_bang(x->mr_outlet); +} + +static void messresponder_float(t_messresponder *x, t_float f) +{ + outlet_float(x->mr_outlet, f); +} + +static void messresponder_symbol(t_messresponder *x, t_symbol *s) +{ + outlet_symbol(x->mr_outlet, s); +} + +static void messresponder_list(t_messresponder *x, + t_symbol *s, int argc, t_atom *argv) +{ + outlet_list(x->mr_outlet, s, argc, argv); +} + +static void messresponder_anything(t_messresponder *x, + t_symbol *s, int argc, t_atom *argv) +{ + outlet_anything(x->mr_outlet, s, argc, argv); +} + +static void message_bang(t_message *x) +{ + binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 0, 0); +} + +static void message_float(t_message *x, t_float f) +{ + t_atom at; + SETFLOAT(&at, f); + binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at); +} + +static void message_symbol(t_message *x, t_symbol *s) +{ + t_atom at; + SETSYMBOL(&at, s); + binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at); +} + +static void message_list(t_message *x, t_symbol *s, int argc, t_atom *argv) +{ + binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, argc, argv); +} + +static void message_set(t_message *x, t_symbol *s, int argc, t_atom *argv) +{ + binbuf_clear(x->m_text.te_binbuf); + binbuf_add(x->m_text.te_binbuf, argc, argv); + glist_retext(x->m_glist, &x->m_text); +} + +static void message_add2(t_message *x, t_symbol *s, int argc, t_atom *argv) +{ + binbuf_add(x->m_text.te_binbuf, argc, argv); + glist_retext(x->m_glist, &x->m_text); +} + +static void message_add(t_message *x, t_symbol *s, int argc, t_atom *argv) +{ + binbuf_add(x->m_text.te_binbuf, argc, argv); + binbuf_addsemi(x->m_text.te_binbuf); + glist_retext(x->m_glist, &x->m_text); +} + +static void message_addcomma(t_message *x) +{ + t_atom a; + SETCOMMA(&a); + binbuf_add(x->m_text.te_binbuf, 1, &a); + glist_retext(x->m_glist, &x->m_text); +} + +static void message_addsemi(t_message *x) +{ + message_add(x, 0, 0, 0); +} + +static void message_adddollar(t_message *x, t_floatarg f) +{ + t_atom a; + int n = f; + if (n < 0) + n = 0; + SETDOLLAR(&a, n); + binbuf_add(x->m_text.te_binbuf, 1, &a); + glist_retext(x->m_glist, &x->m_text); +} + +static void message_adddollsym(t_message *x, t_symbol *s) +{ + t_atom a; + char buf[MAXPDSTRING]; + buf[0] = '$'; + strncpy(buf+1, s->s_name, MAXPDSTRING-2); + buf[MAXPDSTRING-1] = 0; + SETDOLLSYM(&a, gensym(buf)); + binbuf_add(x->m_text.te_binbuf, 1, &a); + glist_retext(x->m_glist, &x->m_text); +} + +static void message_click(t_message *x, + t_floatarg xpos, t_floatarg ypos, t_floatarg shift, + t_floatarg ctrl, t_floatarg alt) +{ + message_float(x, 0); + if (glist_isvisible(x->m_glist)) + { + /* not zooming click width for now as it gets too fat */ + t_rtext *y = glist_findrtext(x->m_glist, &x->m_text); + sys_vgui(".x%lx.c itemconfigure %sR -width %d\n", + glist_getcanvas(x->m_glist), rtext_gettag(y), MESSAGE_CLICK_WIDTH); + clock_delay(x->m_clock, 120); + } +} + +static void message_tick(t_message *x) +{ + if (glist_isvisible(x->m_glist)) + { + t_rtext *y = glist_findrtext(x->m_glist, &x->m_text); + sys_vgui(".x%lx.c itemconfigure %sR -width %d\n", + glist_getcanvas(x->m_glist), rtext_gettag(y), + glist_getzoom(x->m_glist)); + } +} + +static void message_free(t_message *x) +{ + clock_free(x->m_clock); +} + +void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + t_message *x = (t_message *)pd_new(message_class); + x->m_messresponder.mr_pd = messresponder_class; + x->m_messresponder.mr_outlet = outlet_new(&x->m_text, &s_float); + x->m_text.te_width = 0; /* don't know it yet. */ + x->m_text.te_type = T_MESSAGE; + x->m_text.te_binbuf = binbuf_new(); + x->m_glist = gl; + x->m_clock = clock_new(x, (t_method)message_tick); + if (argc > 1) + { + x->m_text.te_xpix = atom_getfloatarg(0, argc, argv); + x->m_text.te_ypix = atom_getfloatarg(1, argc, argv); + if (argc > 2) binbuf_restore(x->m_text.te_binbuf, argc-2, argv+2); + glist_add(gl, &x->m_text.te_g); + } + else if (!glist_isvisible(gl)) + post("unable to create stub message in closed canvas!"); + else + { + int connectme, xpix, ypix, indx, nobj; + canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj); + + pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1); + x->m_text.te_xpix = xpix; + x->m_text.te_ypix = ypix; + glist_add(gl, &x->m_text.te_g); + glist_noselect(gl); + glist_select(gl, &x->m_text.te_g); + gobj_activate(&x->m_text.te_g, gl, 1); + if (connectme) + canvas_connect(gl, indx, 0, nobj, 0); + else canvas_startmotion(glist_getcanvas(gl)); + } +} + +/* ---------------------- the "atom" text item ------------------------ */ + +#define ATOMBUFSIZE 40 +#define ATOM_LABELLEFT 0 +#define ATOM_LABELRIGHT 1 +#define ATOM_LABELUP 2 +#define ATOM_LABELDOWN 3 + +typedef struct _gatom +{ + t_text a_text; + t_atom a_atom; /* this holds the value and the type */ + t_glist *a_glist; /* owning glist */ + t_float a_toggle; /* value to toggle to */ + t_float a_draghi; /* high end of drag range */ + t_float a_draglo; /* low end of drag range */ + t_symbol *a_label; /* symbol to show as label next to box */ + t_symbol *a_symfrom; /* "receive" name -- bind ourselvs to this */ + t_symbol *a_symto; /* "send" name -- send to this on output */ + char a_buf[ATOMBUFSIZE];/* string buffer for typing */ + char a_shift; /* was shift key down when dragging started? */ + char a_wherelabel; /* 0-3 for left, right, above, below */ + t_symbol *a_expanded_to; /* a_symto after $0, $1, ... expansion */ +} t_gatom; + + /* prepend "-" as necessary to avoid empty strings, so we can + use them in Pd messages. A more complete solution would be + to introduce some quoting mechanism; but then we'd be much more + complicated. */ +static t_symbol *gatom_escapit(t_symbol *s) +{ + if (!*s->s_name) + return (gensym("-")); + else if (*s->s_name == '-') + { + char shmo[100]; + shmo[0] = '-'; + strncpy(shmo+1, s->s_name, 99); + shmo[99] = 0; + return (gensym(shmo)); + } + else return (iemgui_dollar2raute(s)); +} + + /* undo previous operation: strip leading "-" if found. */ +static t_symbol *gatom_unescapit(t_symbol *s) +{ + if (*s->s_name == '-') + return (gensym(s->s_name+1)); + else return (iemgui_raute2dollar(s)); +} + +static void gatom_redraw(t_gobj *client, t_glist *glist) +{ + t_gatom *x = (t_gatom *)client; + glist_retext(x->a_glist, &x->a_text); +} + +static void gatom_retext(t_gatom *x, int senditup) +{ + binbuf_clear(x->a_text.te_binbuf); + binbuf_add(x->a_text.te_binbuf, 1, &x->a_atom); + if (senditup && glist_isvisible(x->a_glist)) + sys_queuegui(x, x->a_glist, gatom_redraw); +} + +#ifdef _MSC_VER +#include +#define isnan _isnan +#endif + +static void gatom_set(t_gatom *x, t_symbol *s, int argc, t_atom *argv) +{ + t_atom oldatom = x->a_atom; + int changed = 0; + if (!argc) return; + if (x->a_atom.a_type == A_FLOAT) + { + x->a_atom.a_w.w_float = atom_getfloat(argv); + changed = ((x->a_atom.a_w.w_float != oldatom.a_w.w_float)); + if (isnan(x->a_atom.a_w.w_float) != isnan(oldatom.a_w.w_float)) + changed = 1; + } + else if (x->a_atom.a_type == A_SYMBOL) + x->a_atom.a_w.w_symbol = atom_getsymbol(argv), + changed = (x->a_atom.a_w.w_symbol != oldatom.a_w.w_symbol); + if (changed) + gatom_retext(x, 1); + x->a_buf[0] = 0; +} + +static void gatom_bang(t_gatom *x) +{ + if (x->a_atom.a_type == A_FLOAT) + { + if (x->a_text.te_outlet) + outlet_float(x->a_text.te_outlet, x->a_atom.a_w.w_float); + if (*x->a_expanded_to->s_name && x->a_expanded_to->s_thing) + { + if (x->a_symto == x->a_symfrom) + pd_error(x, + "%s: atom with same send/receive name (infinite loop)", + x->a_symto->s_name); + else pd_float(x->a_expanded_to->s_thing, x->a_atom.a_w.w_float); + } + } + else if (x->a_atom.a_type == A_SYMBOL) + { + if (x->a_text.te_outlet) + outlet_symbol(x->a_text.te_outlet, x->a_atom.a_w.w_symbol); + if (*x->a_symto->s_name && x->a_expanded_to->s_thing) + { + if (x->a_symto == x->a_symfrom) + pd_error(x, + "%s: atom with same send/receive name (infinite loop)", + x->a_symto->s_name); + else pd_symbol(x->a_expanded_to->s_thing, x->a_atom.a_w.w_symbol); + } + } +} + +static void gatom_float(t_gatom *x, t_float f) +{ + t_atom at; + SETFLOAT(&at, f); + gatom_set(x, 0, 1, &at); + gatom_bang(x); +} + +static void gatom_clipfloat(t_gatom *x, t_float f) +{ + if (x->a_draglo != 0 || x->a_draghi != 0) + { + if (f < x->a_draglo) + f = x->a_draglo; + if (f > x->a_draghi) + f = x->a_draghi; + } + gatom_float(x, f); +} + +static void gatom_symbol(t_gatom *x, t_symbol *s) +{ + t_atom at; + SETSYMBOL(&at, s); + gatom_set(x, 0, 1, &at); + gatom_bang(x); +} + + /* We need a list method because, since there's both an "inlet" and a + "nofirstin" flag, the standard list behavior gets confused. */ +static void gatom_list(t_gatom *x, t_symbol *s, int argc, t_atom *argv) +{ + if (!argc) + gatom_bang(x); + else if (argv->a_type == A_FLOAT) + gatom_float(x, argv->a_w.w_float); + else if (argv->a_type == A_SYMBOL) + gatom_symbol(x, argv->a_w.w_symbol); + else pd_error(x, "gatom_list: need float or symbol"); +} + +static void gatom_motion(void *z, t_floatarg dx, t_floatarg dy) +{ + t_gatom *x = (t_gatom *)z; + if (dy == 0) return; + if (x->a_atom.a_type == A_FLOAT) + { + if (x->a_shift) + { + double nval = x->a_atom.a_w.w_float - 0.01 * dy; + double trunc = 0.01 * (floor(100. * nval + 0.5)); + if (trunc < nval + 0.0001 && trunc > nval - 0.0001) nval = trunc; + gatom_clipfloat(x, nval); + } + else + { + double nval = x->a_atom.a_w.w_float - dy; + double trunc = 0.01 * (floor(100. * nval + 0.5)); + if (trunc < nval + 0.0001 && trunc > nval - 0.0001) nval = trunc; + trunc = floor(nval + 0.5); + if (trunc < nval + 0.001 && trunc > nval - 0.001) nval = trunc; + gatom_clipfloat(x, nval); + } + } +} + +static void gatom_key(void *z, t_floatarg f) +{ + t_gatom *x = (t_gatom *)z; + int c = f; + int len = (int)strlen(x->a_buf); + t_atom at; + char sbuf[ATOMBUFSIZE + 4]; + if (c == 0) + { + /* we're being notified that no more keys will come for this grab */ + if (x->a_buf[0]) + gatom_retext(x, 1); + return; + } + else if (c == '\b') + { + if (len > 0) + x->a_buf[len-1] = 0; + goto redraw; + } + else if (c == '\n') + { + if (x->a_atom.a_type == A_FLOAT) + x->a_atom.a_w.w_float = atof(x->a_buf); + else if (x->a_atom.a_type == A_SYMBOL) + x->a_atom.a_w.w_symbol = gensym(x->a_buf); + else bug("gatom_key"); + gatom_bang(x); + gatom_retext(x, 1); + x->a_buf[0] = 0; + } + else if (len < (ATOMBUFSIZE-1)) + { + /* for numbers, only let reasonable characters through */ + if ((x->a_atom.a_type == A_SYMBOL) || + ((c >= '0' && c <= '9') || c == '.' || c == '-' + || c == 'e' || c == 'E')) + { + /* the wchar could expand to up to 4 bytes, which + * which might overrun our a_buf; + * therefore we first expand into a temporary buffer, + * and only if the resulting utf8 string fits into a_buf + * we apply it + */ + char utf8[UTF8_MAXBYTES]; + int utf8len = u8_wc_toutf8(utf8, c); + if((len+utf8len) < (ATOMBUFSIZE-1)) + { + int j=0; + for(j=0; ja_buf[len+j] = utf8[j]; + + x->a_buf[len+utf8len] = 0; + } + goto redraw; + } + } + return; +redraw: + /* LATER figure out how to avoid creating all these symbols! */ + sprintf(sbuf, "%s...", x->a_buf); + SETSYMBOL(&at, gensym(sbuf)); + binbuf_clear(x->a_text.te_binbuf); + binbuf_add(x->a_text.te_binbuf, 1, &at); + glist_retext(x->a_glist, &x->a_text); +} + +static void gatom_click(t_gatom *x, + t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, + t_floatarg alt) +{ + if (x->a_text.te_width == 1) + { + if (x->a_atom.a_type == A_FLOAT) + gatom_float(x, (x->a_atom.a_w.w_float == 0)); + } + else + { + if (alt) + { + if (x->a_atom.a_type != A_FLOAT) return; + if (x->a_atom.a_w.w_float != 0) + { + x->a_toggle = x->a_atom.a_w.w_float; + gatom_float(x, 0); + return; + } + else gatom_float(x, x->a_toggle); + } + x->a_shift = shift; + x->a_buf[0] = 0; + glist_grab(x->a_glist, &x->a_text.te_g, gatom_motion, gatom_key, + xpos, ypos); + } +} + + /* message back from dialog window */ +static void gatom_param(t_gatom *x, t_symbol *sel, int argc, t_atom *argv) +{ + t_float width = atom_getfloatarg(0, argc, argv); + t_float draglo = atom_getfloatarg(1, argc, argv); + t_float draghi = atom_getfloatarg(2, argc, argv); + t_symbol *label = gatom_unescapit(atom_getsymbolarg(3, argc, argv)); + t_float wherelabel = atom_getfloatarg(4, argc, argv); + t_symbol *symfrom = gatom_unescapit(atom_getsymbolarg(5, argc, argv)); + t_symbol *symto = gatom_unescapit(atom_getsymbolarg(6, argc, argv)); + + gobj_vis(&x->a_text.te_g, x->a_glist, 0); + if (!*symfrom->s_name && *x->a_symfrom->s_name) + inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0); + else if (*symfrom->s_name && !*x->a_symfrom->s_name && x->a_text.te_inlet) + { + canvas_deletelinesforio(x->a_glist, &x->a_text, + x->a_text.te_inlet, 0); + inlet_free(x->a_text.te_inlet); + } + if (!*symto->s_name && *x->a_symto->s_name) + outlet_new(&x->a_text, 0); + else if (*symto->s_name && !*x->a_symto->s_name && x->a_text.te_outlet) + { + canvas_deletelinesforio(x->a_glist, &x->a_text, + 0, x->a_text.te_outlet); + outlet_free(x->a_text.te_outlet); + } + if (draglo >= draghi) + draglo = draghi = 0; + x->a_draglo = draglo; + x->a_draghi = draghi; + if (width < 0) + width = 4; + else if (width > 80) + width = 80; + x->a_text.te_width = width; + x->a_wherelabel = ((int)wherelabel & 3); + x->a_label = label; + if (*x->a_symfrom->s_name) + pd_unbind(&x->a_text.te_pd, + canvas_realizedollar(x->a_glist, x->a_symfrom)); + x->a_symfrom = symfrom; + if (*x->a_symfrom->s_name) + pd_bind(&x->a_text.te_pd, + canvas_realizedollar(x->a_glist, x->a_symfrom)); + x->a_symto = symto; + x->a_expanded_to = canvas_realizedollar(x->a_glist, x->a_symto); + gobj_vis(&x->a_text.te_g, x->a_glist, 1); + canvas_dirty(x->a_glist, 1); + + /* glist_retext(x->a_glist, &x->a_text); */ +} + + /* ---------------- gatom-specific widget functions --------------- */ +static void gatom_getwherelabel(t_gatom *x, t_glist *glist, int *xp, int *yp) +{ + int x1, y1, x2, y2, width, height; + text_getrect(&x->a_text.te_g, glist, &x1, &y1, &x2, &y2); + width = x2 - x1; + height = y2 - y1; + if (x->a_wherelabel == ATOM_LABELLEFT) + { + *xp = x1 - 3 - + (int)strlen(canvas_realizedollar(x->a_glist, x->a_label)->s_name) * + glist_fontwidth(glist); + *yp = y1 + 2; + } + else if (x->a_wherelabel == ATOM_LABELRIGHT) + { + *xp = x2 + 2; + *yp = y1 + 2; + } + else if (x->a_wherelabel == ATOM_LABELUP) + { + *xp = x1 - 1; + *yp = y1 - 1 - glist_fontheight(glist); + } + else + { + *xp = x1 - 1; + *yp = y2 + 3; + } +} + +static void gatom_displace(t_gobj *z, t_glist *glist, + int dx, int dy) +{ + t_gatom *x = (t_gatom*)z; + text_displace(z, glist, dx, dy); + sys_vgui(".x%lx.c move %lx.l %d %d\n", glist_getcanvas(glist), + x, dx, dy); +} + +static void gatom_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_gatom *x = (t_gatom*)z; + text_vis(z, glist, vis); + if (*x->a_label->s_name) + { + if (vis) + { + int x1, y1; + gatom_getwherelabel(x, glist, &x1, &y1); + sys_vgui("pdtk_text_new .x%lx.c {%lx.l label text} %f %f {%s} %d %s\n", + glist_getcanvas(glist), x, + (double)x1, (double)y1, + canvas_realizedollar(x->a_glist, x->a_label)->s_name, + sys_hostfontsize(glist_getfont(glist), glist_getzoom(glist)), + "black"); + } + else sys_vgui(".x%lx.c delete %lx.l\n", glist_getcanvas(glist), x); + } + if (!vis) + sys_unqueuegui(x); +} + +void canvas_atom(t_glist *gl, t_atomtype type, + t_symbol *s, int argc, t_atom *argv) +{ + t_gatom *x = (t_gatom *)pd_new(gatom_class); + t_atom at; + x->a_text.te_width = 0; /* don't know it yet. */ + x->a_text.te_type = T_ATOM; + x->a_text.te_binbuf = binbuf_new(); + x->a_glist = gl; + x->a_atom.a_type = type; + x->a_toggle = 1; + x->a_draglo = 0; + x->a_draghi = 0; + x->a_wherelabel = 0; + x->a_label = &s_; + x->a_symfrom = &s_; + x->a_symto = x->a_expanded_to = &s_; + if (type == A_FLOAT) + { + x->a_atom.a_w.w_float = 0; + x->a_text.te_width = 5; + SETFLOAT(&at, 0); + } + else + { + x->a_atom.a_w.w_symbol = &s_symbol; + x->a_text.te_width = 10; + SETSYMBOL(&at, &s_symbol); + } + binbuf_add(x->a_text.te_binbuf, 1, &at); + if (argc > 1) + /* create from file. x, y, width, low-range, high-range, flags, + label, receive-name, send-name */ + { + x->a_text.te_xpix = atom_getfloatarg(0, argc, argv); + x->a_text.te_ypix = atom_getfloatarg(1, argc, argv); + x->a_text.te_width = atom_getfloatarg(2, argc, argv); + /* sanity check because some very old patches have trash in this + field... remove this in 2003 or so: */ + if (x->a_text.te_width < 0 || x->a_text.te_width > 500) + x->a_text.te_width = 4; + x->a_draglo = atom_getfloatarg(3, argc, argv); + x->a_draghi = atom_getfloatarg(4, argc, argv); + x->a_wherelabel = (((int)atom_getfloatarg(5, argc, argv)) & 3); + x->a_label = gatom_unescapit(atom_getsymbolarg(6, argc, argv)); + x->a_symfrom = gatom_unescapit(atom_getsymbolarg(7, argc, argv)); + if (*x->a_symfrom->s_name) + pd_bind(&x->a_text.te_pd, + canvas_realizedollar(x->a_glist, x->a_symfrom)); + + x->a_symto = gatom_unescapit(atom_getsymbolarg(8, argc, argv)); + x->a_expanded_to = canvas_realizedollar(x->a_glist, x->a_symto); + if (x->a_symto == &s_) + outlet_new(&x->a_text, + x->a_atom.a_type == A_FLOAT ? &s_float: &s_symbol); + if (x->a_symfrom == &s_) + inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0); + glist_add(gl, &x->a_text.te_g); + } + else + { + int connectme, xpix, ypix, indx, nobj; + canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj); + outlet_new(&x->a_text, + x->a_atom.a_type == A_FLOAT ? &s_float: &s_symbol); + inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0); + pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1); + x->a_text.te_xpix = xpix; + x->a_text.te_ypix = ypix; + glist_add(gl, &x->a_text.te_g); + glist_noselect(gl); + glist_select(gl, &x->a_text.te_g); + if (connectme) + canvas_connect(gl, indx, 0, nobj, 0); + else canvas_startmotion(glist_getcanvas(gl)); + } +} + +void canvas_floatatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_atom(gl, A_FLOAT, s, argc, argv); +} + +void canvas_symbolatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_atom(gl, A_SYMBOL, s, argc, argv); +} + +static void gatom_free(t_gatom *x) +{ + if (*x->a_symfrom->s_name) + pd_unbind(&x->a_text.te_pd, + canvas_realizedollar(x->a_glist, x->a_symfrom)); + gfxstub_deleteforkey(x); +} + +static void gatom_properties(t_gobj *z, t_glist *owner) +{ + t_gatom *x = (t_gatom *)z; + char buf[200]; + sprintf(buf, "pdtk_gatom_dialog %%s %d %g %g %d {%s} {%s} {%s}\n", + x->a_text.te_width, x->a_draglo, x->a_draghi, + x->a_wherelabel, gatom_escapit(x->a_label)->s_name, + gatom_escapit(x->a_symfrom)->s_name, + gatom_escapit(x->a_symto)->s_name); + gfxstub_new(&x->a_text.te_pd, x, buf); +} + + +/* -------------------- widget behavior for text objects ------------ */ + +static void text_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_text *x = (t_text *)z; + int width, height, iscomment = (x->te_type == T_TEXT); + t_float x1, y1, x2, y2; + + /* for number boxes, we know width and height a priori, and should + report them here so that graphs can get swelled to fit. */ + + if (x->te_type == T_ATOM && x->te_width > 0) + { + width = (x->te_width > 0 ? x->te_width : 6) * glist_fontwidth(glist); + height = glist_fontheight(glist); + if (glist_getzoom(glist) > 1) + { + /* zoom margins */ + width += ATOM_RMARGIN * glist_getzoom(glist); + height += ATOM_BMARGIN * glist_getzoom(glist); + } + else + { + width += ATOM_RMARGIN; + height += ATOM_BMARGIN; + } + } + /* if we're invisible we don't know our size so we just lie about + it. This is called on invisible boxes to establish order of inlets + and possibly other reasons. + To find out if the box is visible we can't just check the "vis" + flag because we might be within the vis() routine and not have set + that yet. So we check directly whether the "rtext" list has been + built. LATER reconsider when "vis" flag should be on and off? */ + + else if (glist->gl_editor && glist->gl_editor->e_rtext) + { + t_rtext *y = glist_findrtext(glist, x); + width = rtext_width(y); + height = rtext_height(y) - (iscomment << 1); + } + else width = height = 10; + x1 = text_xpix(x, glist); + y1 = text_ypix(x, glist); + x2 = x1 + width; + y2 = y1 + height; + y1 += iscomment; + *xp1 = x1; + *yp1 = y1; + *xp2 = x2; + *yp2 = y2; +} + +static void text_displace(t_gobj *z, t_glist *glist, + int dx, int dy) +{ + t_text *x = (t_text *)z; + x->te_xpix += dx; + x->te_ypix += dy; + if (glist_isvisible(glist)) + { + t_rtext *y = glist_findrtext(glist, x); + rtext_displace(y, dx, dy); + text_drawborder(x, glist, rtext_gettag(y), + rtext_width(y), rtext_height(y), 0); + canvas_fixlinesfor(glist, x); + } +} + +static void text_select(t_gobj *z, t_glist *glist, int state) +{ + t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + rtext_select(y, state); + if (glist_isvisible(glist) && gobj_shouldvis(&x->te_g, glist)) + sys_vgui(".x%lx.c itemconfigure %sR -fill %s\n", glist, + rtext_gettag(y), (state? "blue" : "black")); +} + +static void text_activate(t_gobj *z, t_glist *glist, int state) +{ + t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + if (z->g_pd != gatom_class) rtext_activate(y, state); +} + +static void text_delete(t_gobj *z, t_glist *glist) +{ + t_text *x = (t_text *)z; + canvas_deletelinesfor(glist, x); +} + +static void text_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_text *x = (t_text *)z; + if (vis) + { + if (gobj_shouldvis(&x->te_g, glist)) + { + t_rtext *y = glist_findrtext(glist, x); + if (x->te_type == T_ATOM) + glist_retext(glist, x); + text_drawborder(x, glist, rtext_gettag(y), + rtext_width(y), rtext_height(y), 1); + rtext_draw(y); + } + } + else + { + t_rtext *y = glist_findrtext(glist, x); + if (gobj_shouldvis(&x->te_g, glist)) + { + text_eraseborder(x, glist, rtext_gettag(y)); + rtext_erase(y); + } + } +} + +static int text_click(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_text *x = (t_text *)z; + if (x->te_type == T_OBJECT) + { + t_symbol *clicksym = gensym("click"); + if (zgetfn(&x->te_pd, clicksym)) + { + if (doit) + pd_vmess(&x->te_pd, clicksym, "fffff", + (double)xpix, (double)ypix, + (double)shift, (double)0, (double)alt); + return (1); + } + else return (0); + } + else if (x->te_type == T_ATOM) + { + if (doit) + gatom_click((t_gatom *)x, (t_floatarg)xpix, (t_floatarg)ypix, + (t_floatarg)shift, (t_floatarg)0, (t_floatarg)alt); + return (1); + } + else if (x->te_type == T_MESSAGE) + { + if (doit) + message_click((t_message *)x, (t_floatarg)xpix, (t_floatarg)ypix, + (t_floatarg)shift, (t_floatarg)0, (t_floatarg)alt); + return (1); + } + else return (0); +} + +void text_save(t_gobj *z, t_binbuf *b) +{ + t_text *x = (t_text *)z; + if (x->te_type == T_OBJECT) + { + /* if we have a "saveto" method, and if we don't happen to be + a canvas that's an abstraction, the saveto method does the work */ + if (zgetfn(&x->te_pd, gensym("saveto")) && + !((pd_class(&x->te_pd) == canvas_class) && + (canvas_isabstraction((t_canvas *)x) + || canvas_istable((t_canvas *)x)))) + { + mess1(&x->te_pd, gensym("saveto"), b); + binbuf_addv(b, "ssii", gensym("#X"), gensym("restore"), + (int)x->te_xpix, (int)x->te_ypix); + } + else /* otherwise just save the text */ + { + binbuf_addv(b, "ssii", gensym("#X"), gensym("obj"), + (int)x->te_xpix, (int)x->te_ypix); + } + binbuf_addbinbuf(b, x->te_binbuf); + } + else if (x->te_type == T_MESSAGE) + { + binbuf_addv(b, "ssii", gensym("#X"), gensym("msg"), + (int)x->te_xpix, (int)x->te_ypix); + binbuf_addbinbuf(b, x->te_binbuf); + } + else if (x->te_type == T_ATOM) + { + t_atomtype t = ((t_gatom *)x)->a_atom.a_type; + t_symbol *sel = (t == A_SYMBOL ? gensym("symbolatom") : + (t == A_FLOAT ? gensym("floatatom") : gensym("intatom"))); + t_symbol *label = gatom_escapit(((t_gatom *)x)->a_label); + t_symbol *symfrom = gatom_escapit(((t_gatom *)x)->a_symfrom); + t_symbol *symto = gatom_escapit(((t_gatom *)x)->a_symto); + binbuf_addv(b, "ssiiifffsss", gensym("#X"), sel, + (int)x->te_xpix, (int)x->te_ypix, (int)x->te_width, + (double)((t_gatom *)x)->a_draglo, + (double)((t_gatom *)x)->a_draghi, + (double)((t_gatom *)x)->a_wherelabel, + label, symfrom, symto); + } + else + { + binbuf_addv(b, "ssii", gensym("#X"), gensym("text"), + (int)x->te_xpix, (int)x->te_ypix); + binbuf_addbinbuf(b, x->te_binbuf); + } + if (x->te_width) + binbuf_addv(b, ",si", gensym("f"), (int)x->te_width); + binbuf_addv(b, ";"); +} + + /* this one is for everyone but "gatoms"; it's imposed in m_class.c */ +const t_widgetbehavior text_widgetbehavior = +{ + text_getrect, + text_displace, + text_select, + text_activate, + text_delete, + text_vis, + text_click, +}; + +static const t_widgetbehavior gatom_widgetbehavior = +{ + text_getrect, + gatom_displace, + text_select, + text_activate, + text_delete, + gatom_vis, + text_click, +}; + +/* -------------------- the "text" class ------------ */ + + /* draw inlets and outlets for a text object or for a graph. */ +void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime, + char *tag, int x1, int y1, int x2, int y2) +{ + int n = obj_noutlets(ob), nplus = (n == 1 ? 1 : n-1), i; + int width = x2 - x1; + int iow = IOWIDTH * glist->gl_zoom; + int ih = IHEIGHT * glist->gl_zoom, oh = OHEIGHT * glist->gl_zoom; + /* draw over border, so assume border width = 1 pixel * glist->gl_zoom */ + for (i = 0; i < n; i++) + { + int onset = x1 + (width - iow) * i / nplus; + if (firsttime) + sys_vgui(".x%lx.c create rectangle %d %d %d %d " + "-tags [list %so%d outlet] -fill black\n", + glist_getcanvas(glist), + onset, y2 - oh + glist->gl_zoom, + onset + iow, y2, + tag, i); + else + sys_vgui(".x%lx.c coords %so%d %d %d %d %d\n", + glist_getcanvas(glist), tag, i, + onset, y2 - oh + glist->gl_zoom, + onset + iow, y2); + } + n = obj_ninlets(ob); + nplus = (n == 1 ? 1 : n-1); + for (i = 0; i < n; i++) + { + int onset = x1 + (width - iow) * i / nplus; + if (firsttime) + sys_vgui(".x%lx.c create rectangle %d %d %d %d " + "-tags [list %si%d inlet] -fill black\n", + glist_getcanvas(glist), + onset, y1, + onset + iow, y1 + ih - glist->gl_zoom, + tag, i); + else + sys_vgui(".x%lx.c coords %si%d %d %d %d %d\n", + glist_getcanvas(glist), tag, i, + onset, y1, + onset + iow, y1 + ih - glist->gl_zoom); + } +} + +void text_drawborder(t_text *x, t_glist *glist, + char *tag, int width2, int height2, int firsttime) +{ + t_object *ob; + int x1, y1, x2, y2, width, height, corner; + text_getrect(&x->te_g, glist, &x1, &y1, &x2, &y2); + width = x2 - x1; + height = y2 - y1; + if (x->te_type == T_OBJECT) + { + char *pattern = ((pd_class(&x->te_pd) == text_class) ? "-" : "\"\""); + if (firsttime) + sys_vgui(".x%lx.c create line %d %d %d %d %d %d %d %d %d %d " + " -dash %s -width %d -capstyle projecting -tags [list %sR obj]\n", + glist_getcanvas(glist), + x1, y1, x2, y1, x2, y2, x1, y2, x1, y1, pattern, + glist->gl_zoom, tag); + else + { + sys_vgui(".x%lx.c coords %sR %d %d %d %d %d %d %d %d %d %d\n", + glist_getcanvas(glist), tag, + x1, y1, x2, y1, x2, y2, x1, y2, x1, y1); + sys_vgui(".x%lx.c itemconfigure %sR -dash %s\n", + glist_getcanvas(glist), tag, pattern); + } + } + else if (x->te_type == T_MESSAGE) + { + corner = ((y2-y1)/4); + if (corner > 10*glist->gl_zoom) corner = 10*glist->gl_zoom; /* looks bad if too big */ + if (firsttime) + sys_vgui(".x%lx.c create line %d %d %d %d %d %d %d %d %d %d %d %d %d %d " + "-width %d -capstyle projecting -tags [list %sR msg]\n", + glist_getcanvas(glist), + x1, y1, x2+corner, y1, x2, y1+corner, x2, y2-corner, x2+corner, y2, + x1, y2, x1, y1, + glist->gl_zoom, tag); + else + sys_vgui(".x%lx.c coords %sR %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", + glist_getcanvas(glist), tag, + x1, y1, x2+corner, y1, x2, y1+corner, x2, y2-corner, x2+corner, y2, + x1, y2, x1, y1); + } + else if (x->te_type == T_ATOM) + { + corner = ((y2-y1)/4); + if (firsttime) + sys_vgui(".x%lx.c create line %d %d %d %d %d %d %d %d %d %d %d %d " + "-width %d -capstyle projecting -tags [list %sR atom]\n", + glist_getcanvas(glist), + x1, y1, x2-corner, y1, x2, y1+corner, x2, y2, x1, y2, x1, y1, + glist->gl_zoom, tag); + else + sys_vgui(".x%lx.c coords %sR %d %d %d %d %d %d %d %d %d %d %d %d\n", + glist_getcanvas(glist), tag, + x1, y1, x2-corner, y1, x2, y1+corner, x2, y2, x1, y2, x1, y1); + } + /* for comments, just draw a bar on RHS if unlocked; when a visible + canvas is unlocked we have to call this anew on all comments, and when + locked we erase them all via the annoying "commentbar" tag. */ + else if (x->te_type == T_TEXT && glist->gl_edit) + { + if (firsttime) + sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %sR commentbar]\n", + glist_getcanvas(glist), + x2, y1, x2, y2, tag); + else + sys_vgui(".x%lx.c coords %sR %d %d %d %d\n", + glist_getcanvas(glist), tag, x2, y1, x2, y2); + } + /* draw inlets/outlets */ + + if ((ob = pd_checkobject(&x->te_pd))) + glist_drawiofor(glist, ob, firsttime, tag, x1, y1, x2, y2); + if (firsttime) /* raise cords over everything else */ + sys_vgui(".x%lx.c raise cord\n", glist_getcanvas(glist)); +} + +void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag) +{ + int i, n; + n = obj_noutlets(ob); + for (i = 0; i < n; i++) + sys_vgui(".x%lx.c delete %so%d\n", + glist_getcanvas(glist), tag, i); + n = obj_ninlets(ob); + for (i = 0; i < n; i++) + sys_vgui(".x%lx.c delete %si%d\n", + glist_getcanvas(glist), tag, i); +} + +void text_eraseborder(t_text *x, t_glist *glist, char *tag) +{ + if (x->te_type == T_TEXT && !glist->gl_edit) return; + sys_vgui(".x%lx.c delete %sR\n", + glist_getcanvas(glist), tag); + glist_eraseiofor(glist, x, tag); +} + + /* change text; if T_OBJECT, remake it. */ +void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize) +{ + if (x->te_type == T_OBJECT) + { + t_binbuf *b = binbuf_new(); + int natom1, natom2, widthwas = x->te_width; + t_atom *vec1, *vec2; + binbuf_text(b, buf, bufsize); + natom1 = binbuf_getnatom(x->te_binbuf); + vec1 = binbuf_getvec(x->te_binbuf); + natom2 = binbuf_getnatom(b); + vec2 = binbuf_getvec(b); + /* special case: if pd args change just pass the message on. */ + if (natom1 >= 1 && natom2 >= 1 && vec1[0].a_type == A_SYMBOL + && !strcmp(vec1[0].a_w.w_symbol->s_name, "pd") && + vec2[0].a_type == A_SYMBOL + && !strcmp(vec2[0].a_w.w_symbol->s_name, "pd")) + { + typedmess(&x->te_pd, gensym("rename"), natom2-1, vec2+1); + binbuf_free(x->te_binbuf); + x->te_binbuf = b; + } + else /* normally, just destroy the old one and make a new one. */ + { + int xwas = x->te_xpix, ywas = x->te_ypix; + glist_delete(glist, &x->te_g); + canvas_objtext(glist, xwas, ywas, widthwas, 0, b); + canvas_restoreconnections(glist_getcanvas(glist)); + /* if it's an abstraction loadbang it here */ + if (pd_this->pd_newest) + { + if (pd_class(pd_this->pd_newest) == canvas_class) + canvas_loadbang((t_canvas *)pd_this->pd_newest); + else if (zgetfn(pd_this->pd_newest, gensym("loadbang"))) + vmess(pd_this->pd_newest, gensym("loadbang"), "f", LB_LOAD); + } + } + /* if we made a new "pd" or changed a window name, + update window list */ + if (natom2 >= 1 && vec2[0].a_type == A_SYMBOL + && !strcmp(vec2[0].a_w.w_symbol->s_name, "pd")) + canvas_updatewindowlist(); + } + else binbuf_text(x->te_binbuf, buf, bufsize); +} + + /* this gets called when a message gets sent to an object whose creation + failed, presumably because of loading a patch with a missing extern or + abstraction */ +static void text_anything(t_text *x, t_symbol *s, int argc, t_atom *argv) +{ +} + +void g_text_setup(void) +{ + text_class = class_new(gensym("text"), 0, 0, sizeof(t_text), + CLASS_NOINLET | CLASS_PATCHABLE, 0); + class_addanything(text_class, text_anything); + + message_class = class_new(gensym("message"), 0, (t_method)message_free, + sizeof(t_message), CLASS_PATCHABLE, 0); + class_addbang(message_class, message_bang); + class_addfloat(message_class, message_float); + class_addsymbol(message_class, message_symbol); + class_addlist(message_class, message_list); + class_addanything(message_class, message_list); + + class_addmethod(message_class, (t_method)message_click, gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(message_class, (t_method)message_set, gensym("set"), + A_GIMME, 0); + class_addmethod(message_class, (t_method)message_add, gensym("add"), + A_GIMME, 0); + class_addmethod(message_class, (t_method)message_add2, gensym("add2"), + A_GIMME, 0); + class_addmethod(message_class, (t_method)message_addcomma, + gensym("addcomma"), 0); + class_addmethod(message_class, (t_method)message_addsemi, + gensym("addsemi"), 0); + class_addmethod(message_class, (t_method)message_adddollar, + gensym("adddollar"), A_FLOAT, 0); + class_addmethod(message_class, (t_method)message_adddollsym, + gensym("adddollsym"), A_SYMBOL, 0); + + messresponder_class = class_new(gensym("messresponder"), 0, 0, + sizeof(t_text), CLASS_PD, 0); + class_addbang(messresponder_class, messresponder_bang); + class_addfloat(messresponder_class, (t_method) messresponder_float); + class_addsymbol(messresponder_class, messresponder_symbol); + class_addlist(messresponder_class, messresponder_list); + class_addanything(messresponder_class, messresponder_anything); + + gatom_class = class_new(gensym("gatom"), 0, (t_method)gatom_free, + sizeof(t_gatom), CLASS_NOINLET | CLASS_PATCHABLE, 0); + class_addbang(gatom_class, gatom_bang); + class_addfloat(gatom_class, gatom_float); + class_addsymbol(gatom_class, gatom_symbol); + class_addlist(gatom_class, gatom_list); + class_addmethod(gatom_class, (t_method)gatom_set, gensym("set"), + A_GIMME, 0); + class_addmethod(gatom_class, (t_method)gatom_click, gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(gatom_class, (t_method)gatom_param, gensym("param"), + A_GIMME, 0); + class_setwidget(gatom_class, &gatom_widgetbehavior); + class_setpropertiesfn(gatom_class, gatom_properties); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_toggle.c b/ports/camomile/source/LibPd/pure-data/src/g_toggle.c new file mode 100644 index 00000000..99ccdb38 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_toggle.c @@ -0,0 +1,520 @@ +/* Copyright (c) 1997-1999 Miller Puckette. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */ +/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */ + + +#include +#include +#include +#include +#include "m_pd.h" +#include "g_canvas.h" + +#include "g_all_guis.h" +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +/* --------------- tgl gui-toggle ------------------------- */ + +t_widgetbehavior toggle_widgetbehavior; +static t_class *toggle_class; + +/* widget helper functions */ + +void toggle_draw_update(t_toggle *x, t_glist *glist) +{ + if(glist_isvisible(glist)) + { + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c itemconfigure %lxX1 -fill #%06x\n", canvas, x, + (x->x_on != 0.0) ? x->x_gui.x_fcol : x->x_gui.x_bcol); + sys_vgui(".x%lx.c itemconfigure %lxX2 -fill #%06x\n", canvas, x, + (x->x_on != 0.0) ? x->x_gui.x_fcol : x->x_gui.x_bcol); + } +} + +void toggle_draw_new(t_toggle *x, t_glist *glist) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + int crossw = 1, w = x->x_gui.x_w / IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + if(w >= 30) + crossw = 2; + if(w >= 60) + crossw = 3; + crossw *= IEMGUI_ZOOM(x); + + sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -fill #%06x -tags %lxBASE\n", + canvas, xpos, ypos, + xpos + x->x_gui.x_w, ypos + x->x_gui.x_h, + IEMGUI_ZOOM(x), + x->x_gui.x_bcol, x); + sys_vgui(".x%lx.c create line %d %d %d %d -width %d -fill #%06x -tags %lxX1\n", + canvas, + xpos + crossw + IEMGUI_ZOOM(x), ypos + crossw + IEMGUI_ZOOM(x), + xpos + x->x_gui.x_w - crossw - IEMGUI_ZOOM(x), ypos + x->x_gui.x_h - crossw - IEMGUI_ZOOM(x), + crossw, (x->x_on != 0.0) ? x->x_gui.x_fcol : x->x_gui.x_bcol, x); + sys_vgui(".x%lx.c create line %d %d %d %d -width %d -fill #%06x -tags %lxX2\n", + canvas, + xpos + crossw + IEMGUI_ZOOM(x), ypos + x->x_gui.x_h - crossw - IEMGUI_ZOOM(x), + xpos + x->x_gui.x_w - crossw - IEMGUI_ZOOM(x), ypos + crossw + IEMGUI_ZOOM(x), + crossw, (x->x_on != 0.0) ? x->x_gui.x_fcol : x->x_gui.x_bcol, x); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n", + canvas, + xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh, + xpos + iow, ypos + x->x_gui.x_h, + x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n", + canvas, + xpos, ypos, + xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh, + x, 0); + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \ + -font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n", + canvas, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x), + (strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""), + x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + x->x_gui.x_lcol, x); +} + +void toggle_draw_move(t_toggle *x, t_glist *glist) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + int crossw = 1, w = x->x_gui.x_w / IEMGUI_ZOOM(x); + if(w >= 30) + crossw = 2; + if(w >= 60) + crossw = 3; + crossw *= IEMGUI_ZOOM(x); + + sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n", + canvas, x, xpos, ypos, + xpos + x->x_gui.x_w, ypos + x->x_gui.x_h); + sys_vgui(".x%lx.c itemconfigure %lxX1 -width %d\n", canvas, x, crossw); + sys_vgui(".x%lx.c coords %lxX1 %d %d %d %d\n", + canvas, x, + xpos + crossw + IEMGUI_ZOOM(x), ypos + crossw + IEMGUI_ZOOM(x), + xpos + x->x_gui.x_w - crossw, ypos + x->x_gui.x_h - crossw); + sys_vgui(".x%lx.c itemconfigure %lxX2 -width %d\n", canvas, x, crossw); + sys_vgui(".x%lx.c coords %lxX2 %d %d %d %d\n", + canvas, x, + xpos + crossw + IEMGUI_ZOOM(x), ypos + x->x_gui.x_h - crossw - IEMGUI_ZOOM(x), + xpos + x->x_gui.x_w - crossw, ypos + crossw); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n", + canvas, x, 0, + xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh, + xpos + iow, ypos + x->x_gui.x_h); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n", + canvas, x, 0, + xpos, ypos, + xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh); + sys_vgui(".x%lx.c coords %lxLABEL %d %d\n", + canvas, x, + xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x)); +} + +void toggle_draw_erase(t_toggle* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c delete %lxBASE\n", canvas, x); + sys_vgui(".x%lx.c delete %lxX1\n", canvas, x); + sys_vgui(".x%lx.c delete %lxX2\n", canvas, x); + sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); +} + +void toggle_draw_config(t_toggle* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n", + canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + (x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol), + (strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : "")); + sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%06x\n", canvas, x, + x->x_gui.x_bcol); + sys_vgui(".x%lx.c itemconfigure %lxX1 -fill #%06x\n", canvas, x, + x->x_on ? x->x_gui.x_fcol : x->x_gui.x_bcol); + sys_vgui(".x%lx.c itemconfigure %lxX2 -fill #%06x\n", canvas, x, + x->x_on ? x->x_gui.x_fcol : x->x_gui.x_bcol); +} + +void toggle_draw_io(t_toggle* x, t_glist* glist, int old_snd_rcv_flags) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able) { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n", + canvas, + xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh, + xpos + iow, ypos + x->x_gui.x_h, + x, 0); + /* keep above outlet */ + sys_vgui(".x%lx.c raise %lxLABEL %lxOUT%d\n", canvas, x, x, 0); + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able) { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n", + canvas, + xpos, ypos, + xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh, + x, 0); + /* keep above inlet */ + sys_vgui(".x%lx.c raise %lxLABEL %lxIN%d\n", canvas, x, x, 0); + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); +} + +void toggle_draw_select(t_toggle* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + if(x->x_gui.x_fsf.x_selected) + { + sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + } + else + { + sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_NORMAL); + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, x->x_gui.x_lcol); + } +} + +void toggle_draw(t_toggle *x, t_glist *glist, int mode) +{ + if(mode == IEM_GUI_DRAW_MODE_UPDATE) + toggle_draw_update(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_MOVE) + toggle_draw_move(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_NEW) + toggle_draw_new(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_SELECT) + toggle_draw_select(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_ERASE) + toggle_draw_erase(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_CONFIG) + toggle_draw_config(x, glist); + else if(mode >= IEM_GUI_DRAW_MODE_IO) + toggle_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO); +} + +/* ------------------------ tgl widgetbehaviour----------------------------- */ + +static void toggle_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_toggle *x = (t_toggle *)z; + + *xp1 = text_xpix(&x->x_gui.x_obj, glist); + *yp1 = text_ypix(&x->x_gui.x_obj, glist); + *xp2 = *xp1 + x->x_gui.x_w; + *yp2 = *yp1 + x->x_gui.x_h; +} + +static void toggle_save(t_gobj *z, t_binbuf *b) +{ + t_toggle *x = (t_toggle *)z; + t_symbol *bflcol[3]; + t_symbol *srl[3]; + + iemgui_save(&x->x_gui, srl, bflcol); + binbuf_addv(b, "ssiisiisssiiiisssff", gensym("#X"), gensym("obj"), + (int)x->x_gui.x_obj.te_xpix, + (int)x->x_gui.x_obj.te_ypix, + gensym("tgl"), x->x_gui.x_w/IEMGUI_ZOOM(x), + iem_symargstoint(&x->x_gui.x_isa), + srl[0], srl[1], srl[2], + x->x_gui.x_ldx, x->x_gui.x_ldy, + iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize, + bflcol[0], bflcol[1], bflcol[2], x->x_on, x->x_nonzero); + binbuf_addv(b, ";"); +} + +static void toggle_properties(t_gobj *z, t_glist *owner) +{ + t_toggle *x = (t_toggle *)z; + char buf[800]; + t_symbol *srl[3]; + + iemgui_properties(&x->x_gui, srl); + sprintf(buf, "pdtk_iemgui_dialog %%s |tgl| \ + ----------dimensions(pix):----------- %d %d size: 0 0 empty \ + -----------non-zero-value:----------- %g value: 0.0 empty %g \ + -1 lin log %d %d empty %d \ + %s %s \ + %s %d %d \ + %d %d \ + #%06x #%06x #%06x\n", + x->x_gui.x_w/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE, + x->x_nonzero, 1.0,/*non_zero-schedule*/ + x->x_gui.x_isa.x_loadinit, -1, -1,/*no multi*/ + srl[0]->s_name, srl[1]->s_name, + srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy, + x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize, + 0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol); + gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf); +} + +static void toggle_bang(t_toggle *x) +{ + x->x_on = (x->x_on == 0.0) ? x->x_nonzero : 0.0; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + outlet_float(x->x_gui.x_obj.ob_outlet, x->x_on); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, x->x_on); +} + +static void toggle_dialog(t_toggle *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *srl[3]; + int a = (int)atom_getfloatarg(0, argc, argv); + t_float nonzero = (t_float)atom_getfloatarg(2, argc, argv); + int sr_flags; + + if(nonzero == 0.0) + nonzero = 1.0; + x->x_nonzero = nonzero; + if(x->x_on != 0.0) + x->x_on = x->x_nonzero; + sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv); + x->x_gui.x_w = iemgui_clip_size(a) * IEMGUI_ZOOM(x); + x->x_gui.x_h = x->x_gui.x_w; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x); +} + +static void toggle_click(t_toggle *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{toggle_bang(x);} + +static int toggle_newclick(t_gobj *z, struct _glist *glist, int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + if(doit) + toggle_click((t_toggle *)z, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, 0, (t_floatarg)alt); + return (1); +} + +static void toggle_set(t_toggle *x, t_floatarg f) +{ + int old = (x->x_on != 0); + x->x_on = f; + if (f != 0.0 && pd_compatibilitylevel < 46) + x->x_nonzero = f; + if ((x->x_on != 0) != old) + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); +} + +static void toggle_float(t_toggle *x, t_floatarg f) +{ + toggle_set(x, f); + if(x->x_gui.x_fsf.x_put_in2out) + { + outlet_float(x->x_gui.x_obj.ob_outlet, x->x_on); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, x->x_on); + } +} + +static void toggle_fout(t_toggle *x, t_floatarg f) +{ + toggle_set(x, f); + outlet_float(x->x_gui.x_obj.ob_outlet, x->x_on); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, x->x_on); +} + +static void toggle_loadbang(t_toggle *x, t_floatarg action) +{ + if (action == LB_LOAD && x->x_gui.x_isa.x_loadinit) + toggle_fout(x, (t_float)x->x_on); +} + +static void toggle_size(t_toggle *x, t_symbol *s, int ac, t_atom *av) +{ + x->x_gui.x_w = iemgui_clip_size((int)atom_getfloatarg(0, ac, av)) * IEMGUI_ZOOM(x); + x->x_gui.x_h = x->x_gui.x_w; + iemgui_size((void *)x, &x->x_gui); +} + +static void toggle_delta(t_toggle *x, t_symbol *s, int ac, t_atom *av) +{iemgui_delta((void *)x, &x->x_gui, s, ac, av);} + +static void toggle_pos(t_toggle *x, t_symbol *s, int ac, t_atom *av) +{iemgui_pos((void *)x, &x->x_gui, s, ac, av);} + +static void toggle_color(t_toggle *x, t_symbol *s, int ac, t_atom *av) +{iemgui_color((void *)x, &x->x_gui, s, ac, av);} + +static void toggle_send(t_toggle *x, t_symbol *s) +{iemgui_send(x, &x->x_gui, s);} + +static void toggle_receive(t_toggle *x, t_symbol *s) +{iemgui_receive(x, &x->x_gui, s);} + +static void toggle_label(t_toggle *x, t_symbol *s) +{iemgui_label((void *)x, &x->x_gui, s);} + +static void toggle_label_font(t_toggle *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);} + +static void toggle_label_pos(t_toggle *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);} + +static void toggle_init(t_toggle *x, t_floatarg f) +{ + x->x_gui.x_isa.x_loadinit = (f == 0.0) ? 0 : 1; +} + +static void toggle_nonzero(t_toggle *x, t_floatarg f) +{ + if(f != 0.0) + x->x_nonzero = f; +} + +static void *toggle_new(t_symbol *s, int argc, t_atom *argv) +{ + t_toggle *x = (t_toggle *)pd_new(toggle_class); + int a = IEM_GUI_DEFAULTSIZE, f = 0; + int ldx = 17, ldy = 7; + int fs = 10; + t_float on = 0.0, nonzero = 1.0; + char str[144]; + + iem_inttosymargs(&x->x_gui.x_isa, 0); + iem_inttofstyle(&x->x_gui.x_fsf, 0); + + x->x_gui.x_bcol = 0xFCFCFC; + x->x_gui.x_fcol = 0x00; + x->x_gui.x_lcol = 0x00; + + if(((argc == 13)||(argc == 14))&&IS_A_FLOAT(argv,0) + &&IS_A_FLOAT(argv,1) + &&(IS_A_SYMBOL(argv,2)||IS_A_FLOAT(argv,2)) + &&(IS_A_SYMBOL(argv,3)||IS_A_FLOAT(argv,3)) + &&(IS_A_SYMBOL(argv,4)||IS_A_FLOAT(argv,4)) + &&IS_A_FLOAT(argv,5)&&IS_A_FLOAT(argv,6) + &&IS_A_FLOAT(argv,7)&&IS_A_FLOAT(argv,8)&&IS_A_FLOAT(argv,12)) + { + a = (int)atom_getfloatarg(0, argc, argv); + iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(1, argc, argv)); + iemgui_new_getnames(&x->x_gui, 2, argv); + ldx = (int)atom_getfloatarg(5, argc, argv); + ldy = (int)atom_getfloatarg(6, argc, argv); + iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(7, argc, argv)); + fs = (int)atom_getfloatarg(8, argc, argv); + iemgui_all_loadcolors(&x->x_gui, argv+9, argv+10, argv+11); + on = (t_float)atom_getfloatarg(12, argc, argv); + } + else iemgui_new_getnames(&x->x_gui, 2, 0); + if((argc == 14)&&IS_A_FLOAT(argv,13)) + nonzero = (t_float)atom_getfloatarg(13, argc, argv); + x->x_gui.x_draw = (t_iemfunptr)toggle_draw; + + x->x_gui.x_fsf.x_snd_able = 1; + x->x_gui.x_fsf.x_rcv_able = 1; + x->x_gui.x_glist = (t_glist *)canvas_getcurrent(); + if (!strcmp(x->x_gui.x_snd->s_name, "empty")) + x->x_gui.x_fsf.x_snd_able = 0; + if (!strcmp(x->x_gui.x_rcv->s_name, "empty")) + x->x_gui.x_fsf.x_rcv_able = 0; + if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica"); + else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times"); + else { x->x_gui.x_fsf.x_font_style = 0; + strcpy(x->x_gui.x_font, sys_font); } + x->x_nonzero = (nonzero != 0.0) ? nonzero : 1.0; + if(x->x_gui.x_isa.x_loadinit) + x->x_on = (on != 0.0) ? nonzero : 0.0; + else + x->x_on = 0.0; + if (x->x_gui.x_fsf.x_rcv_able) + pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + x->x_gui.x_ldx = ldx; + x->x_gui.x_ldy = ldy; + if(fs < 4) + fs = 4; + x->x_gui.x_fontsize = fs; + x->x_gui.x_w = iemgui_clip_size(a); + x->x_gui.x_h = x->x_gui.x_w; + iemgui_verify_snd_ne_rcv(&x->x_gui); + iemgui_newzoom(&x->x_gui); + outlet_new(&x->x_gui.x_obj, &s_float); + return (x); +} + +static void toggle_ff(t_toggle *x) +{ + if(x->x_gui.x_fsf.x_rcv_able) + pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + gfxstub_deleteforkey(x); +} + +void g_toggle_setup(void) +{ + toggle_class = class_new(gensym("tgl"), (t_newmethod)toggle_new, + (t_method)toggle_ff, sizeof(t_toggle), 0, A_GIMME, 0); + class_addcreator((t_newmethod)toggle_new, gensym("toggle"), A_GIMME, 0); + class_addbang(toggle_class, toggle_bang); + class_addfloat(toggle_class, toggle_float); + class_addmethod(toggle_class, (t_method)toggle_click, gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(toggle_class, (t_method)toggle_dialog, gensym("dialog"), + A_GIMME, 0); + class_addmethod(toggle_class, (t_method)toggle_loadbang, + gensym("loadbang"), A_DEFFLOAT, 0); + class_addmethod(toggle_class, (t_method)toggle_set, gensym("set"), A_FLOAT, 0); + class_addmethod(toggle_class, (t_method)toggle_size, gensym("size"), A_GIMME, 0); + class_addmethod(toggle_class, (t_method)toggle_delta, gensym("delta"), A_GIMME, 0); + class_addmethod(toggle_class, (t_method)toggle_pos, gensym("pos"), A_GIMME, 0); + class_addmethod(toggle_class, (t_method)toggle_color, gensym("color"), A_GIMME, 0); + class_addmethod(toggle_class, (t_method)toggle_send, gensym("send"), A_DEFSYM, 0); + class_addmethod(toggle_class, (t_method)toggle_receive, gensym("receive"), A_DEFSYM, 0); + class_addmethod(toggle_class, (t_method)toggle_label, gensym("label"), A_DEFSYM, 0); + class_addmethod(toggle_class, (t_method)toggle_label_pos, gensym("label_pos"), A_GIMME, 0); + class_addmethod(toggle_class, (t_method)toggle_label_font, gensym("label_font"), A_GIMME, 0); + class_addmethod(toggle_class, (t_method)toggle_init, gensym("init"), A_FLOAT, 0); + class_addmethod(toggle_class, (t_method)toggle_nonzero, gensym("nonzero"), A_FLOAT, 0); + class_addmethod(toggle_class, (t_method)iemgui_zoom, gensym("zoom"), + A_CANT, 0); + toggle_widgetbehavior.w_getrectfn = toggle_getrect; + toggle_widgetbehavior.w_displacefn = iemgui_displace; + toggle_widgetbehavior.w_selectfn = iemgui_select; + toggle_widgetbehavior.w_activatefn = NULL; + toggle_widgetbehavior.w_deletefn = iemgui_delete; + toggle_widgetbehavior.w_visfn = iemgui_vis; + toggle_widgetbehavior.w_clickfn = toggle_newclick; + class_setwidget(toggle_class, &toggle_widgetbehavior); + class_sethelpsymbol(toggle_class, gensym("toggle")); + class_setsavefn(toggle_class, toggle_save); + class_setpropertiesfn(toggle_class, toggle_properties); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_traversal.c b/ports/camomile/source/LibPd/pure-data/src/g_traversal.c new file mode 100644 index 00000000..7a8a2e49 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_traversal.c @@ -0,0 +1,1278 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This file defines Text objects which traverse data contained in scalars +and arrays: + +pointer - point to an object belonging to a template +get - get numeric fields +set - change numeric fields +element - get an array element +getsize - get the size of an array +setsize - change the size of an array +append - add an element to a list +sublist - get a pointer into a list which is an element of another scalar + +*/ + +#include +#include +#include /* for read/write to files */ +#include "m_pd.h" +#include "g_canvas.h" + +/* ------------- gstubs and gpointers - safe pointing --------------- */ + +/* create a gstub which is "owned" by a glist (gl) or an array ("a"). */ + +t_gstub *gstub_new(t_glist *gl, t_array *a) +{ + t_gstub *gs = t_getbytes(sizeof(*gs)); + if (gl) + { + gs->gs_which = GP_GLIST; + gs->gs_un.gs_glist = gl; + } + else + { + gs->gs_which = GP_ARRAY; + gs->gs_un.gs_array = a; + } + gs->gs_refcount = 0; + return (gs); +} + +/* when a "gpointer" is set to point to this stub (so we can later chase +down the owner) we increase a reference count. The following routine is called +whenever a gpointer is unset from pointing here. If the owner is +gone and the refcount goes to zero, we can free the gstub safely. */ + +static void gstub_dis(t_gstub *gs) +{ + int refcount = --gs->gs_refcount; + if ((!refcount) && gs->gs_which == GP_NONE) + t_freebytes(gs, sizeof (*gs)); + else if (refcount < 0) bug("gstub_dis"); +} + +/* this routing is called by the owner to inform the gstub that it is +being deleted. If no gpointers are pointing here, we can free the gstub; +otherwise we wait for the last gstub_dis() to free it. */ + +void gstub_cutoff(t_gstub *gs) +{ + gs->gs_which = GP_NONE; + if (gs->gs_refcount < 0) bug("gstub_cutoff"); + if (!gs->gs_refcount) t_freebytes(gs, sizeof (*gs)); +} + +/* call this to verify that a pointer is fresh, i.e., that it either +points to real data or to the head of a list, and that in either case +the object hasn't disappeared since this pointer was generated. +Unless "headok" is set, the routine also fails for the head of a list. */ + +int gpointer_check(const t_gpointer *gp, int headok) +{ + t_gstub *gs = gp->gp_stub; + if (!gs) return (0); + if (gs->gs_which == GP_ARRAY) + { + if (gs->gs_un.gs_array->a_valid != gp->gp_valid) return (0); + else return (1); + } + else if (gs->gs_which == GP_GLIST) + { + if (!headok && !gp->gp_un.gp_scalar) return (0); + else if (gs->gs_un.gs_glist->gl_valid != gp->gp_valid) return (0); + else return (1); + } + else return (0); +} + +/* get the template for the object pointer to. Assumes we've already checked +freshness. */ + +static t_symbol *gpointer_gettemplatesym(const t_gpointer *gp) +{ + t_gstub *gs = gp->gp_stub; + if (gs->gs_which == GP_GLIST) + { + t_scalar *sc = gp->gp_un.gp_scalar; + if (sc) + return (sc->sc_template); + else return (0); + } + else + { + t_array *a = gs->gs_un.gs_array; + return (a->a_templatesym); + } +} + + /* copy a pointer to another, assuming the second one hasn't yet been + initialized. New gpointers should be initialized either by this + routine or by gpointer_init below. */ +void gpointer_copy(const t_gpointer *gpfrom, t_gpointer *gpto) +{ + *gpto = *gpfrom; + if (gpto->gp_stub) + gpto->gp_stub->gs_refcount++; + else bug("gpointer_copy"); +} + + /* clear a gpointer that was previously set, releasing the associted + gstub if this was the last reference to it. */ +void gpointer_unset(t_gpointer *gp) +{ + t_gstub *gs; + if ((gs = gp->gp_stub)) + { + gstub_dis(gs); + gp->gp_stub = 0; + } +} + +void gpointer_setglist(t_gpointer *gp, t_glist *glist, t_scalar *x) +{ + t_gstub *gs; + if ((gs = gp->gp_stub)) gstub_dis(gs); + gp->gp_stub = gs = glist->gl_stub; + gp->gp_valid = glist->gl_valid; + gp->gp_un.gp_scalar = x; + gs->gs_refcount++; +} + +void gpointer_setarray(t_gpointer *gp, t_array *array, t_word *w) +{ + t_gstub *gs; + if ((gs = gp->gp_stub)) gstub_dis(gs); + gp->gp_stub = gs = array->a_stub; + gp->gp_valid = array->a_valid; + gp->gp_un.gp_w = w; + gs->gs_refcount++; +} + +void gpointer_init(t_gpointer *gp) +{ + gp->gp_stub = 0; + gp->gp_valid = 0; + gp->gp_un.gp_scalar = 0; +} + +/********* random utility function to find a binbuf in a datum */ + +t_binbuf *pointertobinbuf(t_pd *x, t_gpointer *gp, t_symbol *s, + const char *fname) +{ + t_symbol *templatesym = gpointer_gettemplatesym(gp), *arraytype; + t_template *template; + int onset, type; + t_binbuf *b; + t_gstub *gs = gp->gp_stub; + t_word *vec; + if (!templatesym) + { + pd_error(x, "%s: bad pointer", fname); + return (0); + } + if (!(template = template_findbyname(templatesym))) + { + pd_error(x, "%s: couldn't find template %s", fname, + templatesym->s_name); + return (0); + } + if (!template_find_field(template, s, &onset, &type, &arraytype)) + { + pd_error(x, "%s: %s.%s: no such field", fname, + templatesym->s_name, s->s_name); + return (0); + } + if (type != DT_TEXT) + { + pd_error(x, "%s: %s.%s: not a list", fname, + templatesym->s_name, s->s_name); + return (0); + } + if (gs->gs_which == GP_ARRAY) + vec = gp->gp_un.gp_w; + else vec = gp->gp_un.gp_scalar->sc_vec; + return (vec[onset].w_binbuf); +} + + /* templates are named using the name-bashing by which canvases bind + thenselves, with a leading "pd-". LATER see if we can have templates + occupy their real names. Meanwhile, if a template has an empty name + or is named "-" (as when passed as a "-" argument to "get", etc.), just + return &s_; objects should check for this and allow it as a wild + card when appropriate. */ +static t_symbol *template_getbindsym(t_symbol *s) +{ + if (!*s->s_name || !strcmp(s->s_name, "-")) + return (&s_); + else return (canvas_makebindsym(s)); +} + +/* ---------------------- pointers ----------------------------- */ + +static t_class *ptrobj_class; + +typedef struct +{ + t_symbol *to_type; + t_outlet *to_outlet; +} t_typedout; + +typedef struct _ptrobj +{ + t_object x_obj; + t_gpointer x_gp; + t_typedout *x_typedout; + int x_ntypedout; + t_outlet *x_otherout; + t_outlet *x_bangout; +} t_ptrobj; + +static void *ptrobj_new(t_symbol *classname, int argc, t_atom *argv) +{ + t_ptrobj *x = (t_ptrobj *)pd_new(ptrobj_class); + t_typedout *to; + int n; + gpointer_init(&x->x_gp); + x->x_typedout = to = (t_typedout *)getbytes(argc * sizeof (*to)); + x->x_ntypedout = n = argc; + for (; n--; to++) + { + to->to_outlet = outlet_new(&x->x_obj, &s_pointer); + to->to_type = template_getbindsym(atom_getsymbol(argv++)); + } + x->x_otherout = outlet_new(&x->x_obj, &s_pointer); + x->x_bangout = outlet_new(&x->x_obj, &s_bang); + pointerinlet_new(&x->x_obj, &x->x_gp); + return (x); +} + +static void ptrobj_traverse(t_ptrobj *x, t_symbol *s) +{ + t_glist *glist = (t_glist *)pd_findbyclass(s, canvas_class); + if (glist) gpointer_setglist(&x->x_gp, glist, 0); + else pd_error(x, "pointer: list '%s' not found", s->s_name); +} + +static void ptrobj_vnext(t_ptrobj *x, t_float f) +{ + t_gobj *gobj; + t_gpointer *gp = &x->x_gp; + t_gstub *gs = gp->gp_stub; + t_glist *glist; + int wantselected = (f != 0); + + if (!gs) + { + pd_error(x, "ptrobj_next: no current pointer"); + return; + } + if (gs->gs_which != GP_GLIST) + { + pd_error(x, "ptrobj_next: lists only, not arrays"); + return; + } + glist = gs->gs_un.gs_glist; + if (glist->gl_valid != gp->gp_valid) + { + pd_error(x, "ptrobj_next: stale pointer"); + return; + } + if (wantselected && !glist_isvisible(glist)) + { + pd_error(x, + "ptrobj_vnext: next-selected only works for a visible window"); + return; + } + gobj = &gp->gp_un.gp_scalar->sc_gobj; + + if (!gobj) gobj = glist->gl_list; + else gobj = gobj->g_next; + while (gobj && ((pd_class(&gobj->g_pd) != scalar_class) || + (wantselected && !glist_isselected(glist, gobj)))) + gobj = gobj->g_next; + + if (gobj) + { + t_typedout *to; + int n; + t_scalar *sc = (t_scalar *)gobj; + t_symbol *templatesym = sc->sc_template; + + gp->gp_un.gp_scalar = sc; + for (n = x->x_ntypedout, to = x->x_typedout; n--; to++) + { + if (to->to_type == templatesym) + { + outlet_pointer(to->to_outlet, &x->x_gp); + return; + } + } + outlet_pointer(x->x_otherout, &x->x_gp); + } + else + { + gpointer_unset(gp); + outlet_bang(x->x_bangout); + } +} + +static void ptrobj_next(t_ptrobj *x) +{ + ptrobj_vnext(x, 0); +} + + /* send a message to the window containing the object pointed to */ +static void ptrobj_sendwindow(t_ptrobj *x, t_symbol *s, int argc, t_atom *argv) +{ + t_scalar *sc; + t_symbol *templatesym; + int n; + t_typedout *to; + t_glist *glist; + t_pd *canvas; + t_gstub *gs; + if (!gpointer_check(&x->x_gp, 1)) + { + pd_error(x, "send-window: empty pointer"); + return; + } + gs = x->x_gp.gp_stub; + if (gs->gs_which == GP_GLIST) + glist = gs->gs_un.gs_glist; + else + { + t_array *owner_array = gs->gs_un.gs_array; + while (owner_array->a_gp.gp_stub->gs_which == GP_ARRAY) + owner_array = owner_array->a_gp.gp_stub->gs_un.gs_array; + glist = owner_array->a_gp.gp_stub->gs_un.gs_glist; + } + canvas = (t_pd *)glist_getcanvas(glist); + if (argc && argv->a_type == A_SYMBOL) + pd_typedmess(canvas, argv->a_w.w_symbol, argc-1, argv+1); + else pd_error(x, "send-window: no message?"); +} + + + /* send the pointer to the named object */ +static void ptrobj_send(t_ptrobj *x, t_symbol *s) +{ + if (!s->s_thing) + pd_error(x, "%s: no such object", s->s_name); + else if (!gpointer_check(&x->x_gp, 1)) + pd_error(x, "pointer_send: empty pointer"); + else pd_pointer(s->s_thing, &x->x_gp); +} + +static void ptrobj_bang(t_ptrobj *x) +{ + t_symbol *templatesym; + int n; + t_typedout *to; + if (!gpointer_check(&x->x_gp, 1)) + { + pd_error(x, "pointer_bang: empty pointer"); + return; + } + templatesym = gpointer_gettemplatesym(&x->x_gp); + for (n = x->x_ntypedout, to = x->x_typedout; n--; to++) + { + if (to->to_type == templatesym) + { + outlet_pointer(to->to_outlet, &x->x_gp); + return; + } + } + outlet_pointer(x->x_otherout, &x->x_gp); +} + + +static void ptrobj_pointer(t_ptrobj *x, t_gpointer *gp) +{ + gpointer_unset(&x->x_gp); + gpointer_copy(gp, &x->x_gp); + ptrobj_bang(x); +} + + +static void ptrobj_rewind(t_ptrobj *x) +{ + t_scalar *sc; + t_symbol *templatesym; + int n; + t_typedout *to; + t_glist *glist; + t_pd *canvas; + t_gstub *gs; + if (!gpointer_check(&x->x_gp, 1)) + { + pd_error(x, "pointer_rewind: empty pointer"); + return; + } + gs = x->x_gp.gp_stub; + if (gs->gs_which != GP_GLIST) + { + pd_error(x, "pointer_rewind: sorry, unavailable for arrays"); + return; + } + glist = gs->gs_un.gs_glist; + gpointer_setglist(&x->x_gp, glist, 0); + ptrobj_bang(x); +} + +static void ptrobj_free(t_ptrobj *x) +{ + freebytes(x->x_typedout, x->x_ntypedout * sizeof (*x->x_typedout)); + gpointer_unset(&x->x_gp); +} + +static void ptrobj_setup(void) +{ + ptrobj_class = class_new(gensym("pointer"), (t_newmethod)ptrobj_new, + (t_method)ptrobj_free, sizeof(t_ptrobj), 0, A_GIMME, 0); + class_addmethod(ptrobj_class, (t_method)ptrobj_next, gensym("next"), 0); + class_addmethod(ptrobj_class, (t_method)ptrobj_send, gensym("send"), + A_SYMBOL, 0); + class_addmethod(ptrobj_class, (t_method)ptrobj_traverse, gensym("traverse"), + A_SYMBOL, 0); + class_addmethod(ptrobj_class, (t_method)ptrobj_vnext, gensym("vnext"), + A_DEFFLOAT, 0); + class_addmethod(ptrobj_class, (t_method)ptrobj_sendwindow, + gensym("send-window"), A_GIMME, 0); + class_addmethod(ptrobj_class, (t_method)ptrobj_rewind, + gensym("rewind"), 0); + class_addpointer(ptrobj_class, ptrobj_pointer); + class_addbang(ptrobj_class, ptrobj_bang); +} + +/* ---------------------- get ----------------------------- */ + +static t_class *get_class; + +typedef struct _getvariable +{ + t_symbol *gv_sym; + t_outlet *gv_outlet; +} t_getvariable; + +typedef struct _get +{ + t_object x_obj; + t_symbol *x_templatesym; + int x_nout; + t_getvariable *x_variables; +} t_get; + +static void *get_new(t_symbol *why, int argc, t_atom *argv) +{ + t_get *x = (t_get *)pd_new(get_class); + int varcount, i; + t_atom at, *varvec; + t_getvariable *sp; + + x->x_templatesym = template_getbindsym(atom_getsymbolarg(0, argc, argv)); + if (argc < 2) + { + varcount = 1; + varvec = &at; + SETSYMBOL(&at, &s_); + } + else varcount = argc - 1, varvec = argv + 1; + x->x_variables + = (t_getvariable *)getbytes(varcount * sizeof (*x->x_variables)); + x->x_nout = varcount; + for (i = 0, sp = x->x_variables; i < varcount; i++, sp++) + { + sp->gv_sym = atom_getsymbolarg(i, varcount, varvec); + sp->gv_outlet = outlet_new(&x->x_obj, 0); + /* LATER connect with the template and set the outlet's type + correctly. We can't yet guarantee that the template is there + before we hit this routine. */ + } + return (x); +} + +static void get_set(t_get *x, t_symbol *templatesym, t_symbol *field) +{ + if (x->x_nout != 1) + pd_error(x, "get: cannot set multiple fields."); + else + { + x->x_templatesym = template_getbindsym(templatesym); + x->x_variables->gv_sym = field; + } +} + +static void get_pointer(t_get *x, t_gpointer *gp) +{ + int nitems = x->x_nout, i; + t_symbol *templatesym; + t_template *template; + t_gstub *gs = gp->gp_stub; + t_word *vec; + t_getvariable *vp; + + if (!gpointer_check(gp, 0)) + { + pd_error(x, "get: stale or empty pointer"); + return; + } + if (*x->x_templatesym->s_name) + { + if ((templatesym = x->x_templatesym) != gpointer_gettemplatesym(gp)) + { + pd_error(x, "get %s: got wrong template (%s)", + templatesym->s_name, gpointer_gettemplatesym(gp)->s_name); + return; + } + } + else templatesym = gpointer_gettemplatesym(gp); + if (!(template = template_findbyname(templatesym))) + { + pd_error(x, "get: couldn't find template %s", templatesym->s_name); + return; + } + if (gs->gs_which == GP_ARRAY) vec = gp->gp_un.gp_w; + else vec = gp->gp_un.gp_scalar->sc_vec; + for (i = nitems - 1, vp = x->x_variables + i; i >= 0; i--, vp--) + { + int onset, type; + t_symbol *arraytype; + if (template_find_field(template, vp->gv_sym, &onset, &type, &arraytype)) + { + if (type == DT_FLOAT) + outlet_float(vp->gv_outlet, + *(t_float *)(((char *)vec) + onset)); + else if (type == DT_SYMBOL) + outlet_symbol(vp->gv_outlet, + *(t_symbol **)(((char *)vec) + onset)); + else pd_error(x, "get: %s.%s is not a number or symbol", + template->t_sym->s_name, vp->gv_sym->s_name); + } + else pd_error(x, "get: %s.%s: no such field", + template->t_sym->s_name, vp->gv_sym->s_name); + } +} + +static void get_free(t_get *x) +{ + freebytes(x->x_variables, x->x_nout * sizeof (*x->x_variables)); +} + +static void get_setup(void) +{ + get_class = class_new(gensym("get"), (t_newmethod)get_new, + (t_method)get_free, sizeof(t_get), 0, A_GIMME, 0); + class_addpointer(get_class, get_pointer); + class_addmethod(get_class, (t_method)get_set, gensym("set"), + A_SYMBOL, A_SYMBOL, 0); +} + +/* ---------------------- set ----------------------------- */ + +static t_class *set_class; + +typedef struct _setvariable +{ + t_symbol *gv_sym; + union word gv_w; +} t_setvariable; + +typedef struct _set +{ + t_object x_obj; + t_gpointer x_gp; + t_symbol *x_templatesym; + int x_nin; + int x_issymbol; + t_setvariable *x_variables; +} t_set; + +static void *set_new(t_symbol *why, int argc, t_atom *argv) +{ + t_set *x = (t_set *)pd_new(set_class); + int i, varcount; + t_setvariable *sp; + t_atom at, *varvec; + if (argc && (argv[0].a_type == A_SYMBOL) && + !strcmp(argv[0].a_w.w_symbol->s_name, "-symbol")) + { + x->x_issymbol = 1; + argc--; + argv++; + } + else x->x_issymbol = 0; + x->x_templatesym = template_getbindsym(atom_getsymbolarg(0, argc, argv)); + if (argc < 2) + { + varcount = 1; + varvec = &at; + SETSYMBOL(&at, &s_); + } + else varcount = argc - 1, varvec = argv + 1; + x->x_variables + = (t_setvariable *)getbytes(varcount * sizeof (*x->x_variables)); + x->x_nin = varcount; + for (i = 0, sp = x->x_variables; i < varcount; i++, sp++) + { + sp->gv_sym = atom_getsymbolarg(i, varcount, varvec); + if (x->x_issymbol) + sp->gv_w.w_symbol = &s_; + else sp->gv_w.w_float = 0; + if (i) + { + if (x->x_issymbol) + symbolinlet_new(&x->x_obj, &sp->gv_w.w_symbol); + else floatinlet_new(&x->x_obj, &sp->gv_w.w_float); + } + } + pointerinlet_new(&x->x_obj, &x->x_gp); + gpointer_init(&x->x_gp); + return (x); +} + +static void set_set(t_set *x, t_symbol *templatesym, t_symbol *field) +{ + if (x->x_nin != 1) + pd_error(x, "set: cannot set multiple fields."); + else + { + x->x_templatesym = template_getbindsym(templatesym); + x->x_variables->gv_sym = field; + if (x->x_issymbol) + x->x_variables->gv_w.w_symbol = &s_; + else + x->x_variables->gv_w.w_float = 0; + } +} + +static void set_bang(t_set *x) +{ + int nitems = x->x_nin, i; + t_symbol *templatesym; + t_template *template; + t_setvariable *vp; + t_gpointer *gp = &x->x_gp; + t_gstub *gs = gp->gp_stub; + t_word *vec; + if (!gpointer_check(gp, 0)) + { + pd_error(x, "set: empty pointer"); + return; + } + if (*x->x_templatesym->s_name) + { + if ((templatesym = x->x_templatesym) != gpointer_gettemplatesym(gp)) + { + pd_error(x, "set %s: got wrong template (%s)", + templatesym->s_name, gpointer_gettemplatesym(gp)->s_name); + return; + } + } + else templatesym = gpointer_gettemplatesym(gp); + if (!(template = template_findbyname(templatesym))) + { + pd_error(x, "set: couldn't find template %s", templatesym->s_name); + return; + } + if (!nitems) + return; + if (gs->gs_which == GP_ARRAY) + vec = gp->gp_un.gp_w; + else vec = gp->gp_un.gp_scalar->sc_vec; + if (x->x_issymbol) + for (i = 0, vp = x->x_variables; i < nitems; i++, vp++) + template_setsymbol(template, vp->gv_sym, vec, vp->gv_w.w_symbol, 1); + else for (i = 0, vp = x->x_variables; i < nitems; i++, vp++) + template_setfloat(template, vp->gv_sym, vec, vp->gv_w.w_float, 1); + if (gs->gs_which == GP_GLIST) + scalar_redraw(gp->gp_un.gp_scalar, gs->gs_un.gs_glist); + else + { + t_array *owner_array = gs->gs_un.gs_array; + while (owner_array->a_gp.gp_stub->gs_which == GP_ARRAY) + owner_array = owner_array->a_gp.gp_stub->gs_un.gs_array; + scalar_redraw(owner_array->a_gp.gp_un.gp_scalar, + owner_array->a_gp.gp_stub->gs_un.gs_glist); + } +} + +static void set_float(t_set *x, t_float f) +{ + if (x->x_nin && !x->x_issymbol) + { + x->x_variables[0].gv_w.w_float = f; + set_bang(x); + } + else pd_error(x, "type mismatch or no field specified"); +} + +static void set_symbol(t_set *x, t_symbol *s) +{ + if (x->x_nin && x->x_issymbol) + { + x->x_variables[0].gv_w.w_symbol = s; + set_bang(x); + } + else pd_error(x, "type mismatch or no field specified"); +} + +static void set_free(t_set *x) +{ + freebytes(x->x_variables, x->x_nin * sizeof (*x->x_variables)); + gpointer_unset(&x->x_gp); +} + +static void set_setup(void) +{ + set_class = class_new(gensym("set"), (t_newmethod)set_new, + (t_method)set_free, sizeof(t_set), 0, A_GIMME, 0); + class_addfloat(set_class, set_float); + class_addsymbol(set_class, set_symbol); + class_addbang(set_class, set_bang); + class_addmethod(set_class, (t_method)set_set, gensym("set"), + A_SYMBOL, A_SYMBOL, 0); +} + +/* ---------------------- elem ----------------------------- */ + +static t_class *elem_class; + +typedef struct _elem +{ + t_object x_obj; + t_symbol *x_templatesym; + t_symbol *x_fieldsym; + t_gpointer x_gp; + t_gpointer x_gparent; +} t_elem; + +static void *elem_new(t_symbol *templatesym, t_symbol *fieldsym) +{ + t_elem *x = (t_elem *)pd_new(elem_class); + x->x_templatesym = template_getbindsym(templatesym); + x->x_fieldsym = fieldsym; + gpointer_init(&x->x_gp); + gpointer_init(&x->x_gparent); + pointerinlet_new(&x->x_obj, &x->x_gparent); + outlet_new(&x->x_obj, &s_pointer); + return (x); +} + +static void elem_set(t_elem *x, t_symbol *templatesym, t_symbol *fieldsym) +{ + x->x_templatesym = template_getbindsym(templatesym); + x->x_fieldsym = fieldsym; +} + +static void elem_float(t_elem *x, t_float f) +{ + int indx = f, nitems, onset; + t_symbol *templatesym, *fieldsym = x->x_fieldsym, *elemtemplatesym; + t_template *template; + t_template *elemtemplate; + t_gpointer *gparent = &x->x_gparent; + t_word *w; + t_array *array; + int elemsize, type; + + if (!gpointer_check(gparent, 0)) + { + pd_error(x, "element: empty pointer"); + return; + } + if (*x->x_templatesym->s_name) + { + if ((templatesym = x->x_templatesym) != + gpointer_gettemplatesym(gparent)) + { + pd_error(x, "elem %s: got wrong template (%s)", + templatesym->s_name, gpointer_gettemplatesym(gparent)->s_name); + return; + } + } + else templatesym = gpointer_gettemplatesym(gparent); + if (!(template = template_findbyname(templatesym))) + { + pd_error(x, "elem: couldn't find template %s", templatesym->s_name); + return; + } + if (gparent->gp_stub->gs_which == GP_ARRAY) w = gparent->gp_un.gp_w; + else w = gparent->gp_un.gp_scalar->sc_vec; + if (!template) + { + pd_error(x, "element: couldn't find template %s", templatesym->s_name); + return; + } + if (!template_find_field(template, fieldsym, + &onset, &type, &elemtemplatesym)) + { + pd_error(x, "element: couldn't find array field %s", fieldsym->s_name); + return; + } + if (type != DT_ARRAY) + { + pd_error(x, "element: field %s not of type array", fieldsym->s_name); + return; + } + if (!(elemtemplate = template_findbyname(elemtemplatesym))) + { + pd_error(x, "element: couldn't find field template %s", + elemtemplatesym->s_name); + return; + } + + elemsize = elemtemplate->t_n * sizeof(t_word); + + array = *(t_array **)(((char *)w) + onset); + + nitems = array->a_n; + if (indx < 0) indx = 0; + if (indx >= nitems) indx = nitems-1; + + gpointer_setarray(&x->x_gp, array, + (t_word *)((char *)(array->a_vec) + indx * elemsize)); + outlet_pointer(x->x_obj.ob_outlet, &x->x_gp); +} + +static void elem_free(t_elem *x, t_gpointer *gp) +{ + gpointer_unset(&x->x_gp); + gpointer_unset(&x->x_gparent); +} + +static void elem_setup(void) +{ + elem_class = class_new(gensym("element"), (t_newmethod)elem_new, + (t_method)elem_free, sizeof(t_elem), 0, A_DEFSYM, A_DEFSYM, 0); + class_addfloat(elem_class, elem_float); + class_addmethod(elem_class, (t_method)elem_set, gensym("set"), + A_SYMBOL, A_SYMBOL, 0); +} + +/* ---------------------- getsize ----------------------------- */ + +static t_class *getsize_class; + +typedef struct _getsize +{ + t_object x_obj; + t_symbol *x_templatesym; + t_symbol *x_fieldsym; +} t_getsize; + +static void *getsize_new(t_symbol *templatesym, t_symbol *fieldsym) +{ + t_getsize *x = (t_getsize *)pd_new(getsize_class); + x->x_templatesym = template_getbindsym(templatesym); + x->x_fieldsym = fieldsym; + outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void getsize_set(t_getsize *x, t_symbol *templatesym, t_symbol *fieldsym) +{ + x->x_templatesym = template_getbindsym(templatesym); + x->x_fieldsym = fieldsym; +} + +static void getsize_pointer(t_getsize *x, t_gpointer *gp) +{ + int nitems, onset, type; + t_symbol *templatesym, *fieldsym = x->x_fieldsym, *elemtemplatesym; + t_template *template; + t_word *w; + t_array *array; + int elemsize; + t_gstub *gs = gp->gp_stub; + if (!gpointer_check(gp, 0)) + { + pd_error(x, "getsize: stale or empty pointer"); + return; + } + if (*x->x_templatesym->s_name) + { + if ((templatesym = x->x_templatesym) != + gpointer_gettemplatesym(gp)) + { + pd_error(x, "elem %s: got wrong template (%s)", + templatesym->s_name, gpointer_gettemplatesym(gp)->s_name); + return; + } + } + else templatesym = gpointer_gettemplatesym(gp); + if (!(template = template_findbyname(templatesym))) + { + pd_error(x, "elem: couldn't find template %s", templatesym->s_name); + return; + } + if (!template_find_field(template, fieldsym, + &onset, &type, &elemtemplatesym)) + { + pd_error(x, "getsize: couldn't find array field %s", fieldsym->s_name); + return; + } + if (type != DT_ARRAY) + { + pd_error(x, "getsize: field %s not of type array", fieldsym->s_name); + return; + } + if (gs->gs_which == GP_ARRAY) w = gp->gp_un.gp_w; + else w = gp->gp_un.gp_scalar->sc_vec; + + array = *(t_array **)(((char *)w) + onset); + outlet_float(x->x_obj.ob_outlet, (t_float)(array->a_n)); +} + +static void getsize_setup(void) +{ + getsize_class = class_new(gensym("getsize"), (t_newmethod)getsize_new, 0, + sizeof(t_getsize), 0, A_DEFSYM, A_DEFSYM, 0); + class_addpointer(getsize_class, getsize_pointer); + class_addmethod(getsize_class, (t_method)getsize_set, gensym("set"), + A_SYMBOL, A_SYMBOL, 0); +} + +/* ---------------------- setsize ----------------------------- */ + +static t_class *setsize_class; + +typedef struct _setsize +{ + t_object x_obj; + t_symbol *x_templatesym; + t_symbol *x_fieldsym; + t_gpointer x_gp; +} t_setsize; + +static void *setsize_new(t_symbol *templatesym, t_symbol *fieldsym, + t_floatarg newsize) +{ + t_setsize *x = (t_setsize *)pd_new(setsize_class); + x->x_templatesym = template_getbindsym(templatesym); + x->x_fieldsym = fieldsym; + gpointer_init(&x->x_gp); + + pointerinlet_new(&x->x_obj, &x->x_gp); + return (x); +} + +static void setsize_set(t_setsize *x, t_symbol *templatesym, t_symbol *fieldsym) +{ + x->x_templatesym = template_getbindsym(templatesym); + x->x_fieldsym = fieldsym; +} + +static void setsize_float(t_setsize *x, t_float f) +{ + int nitems, onset, type; + t_symbol *templatesym, *fieldsym = x->x_fieldsym, *elemtemplatesym; + t_template *template; + t_template *elemtemplate; + t_word *w; + t_atom at; + t_array *array; + int elemsize; + int newsize = f; + t_gpointer *gp = &x->x_gp; + t_gstub *gs = gp->gp_stub; + if (!gpointer_check(&x->x_gp, 0)) + { + pd_error(x, "setsize: empty pointer"); + return; + } + if (*x->x_templatesym->s_name) + { + if ((templatesym = x->x_templatesym) != + gpointer_gettemplatesym(gp)) + { + pd_error(x, "elem %s: got wrong template (%s)", + templatesym->s_name, gpointer_gettemplatesym(gp)->s_name); + return; + } + } + else templatesym = gpointer_gettemplatesym(gp); + if (!(template = template_findbyname(templatesym))) + { + pd_error(x, "elem: couldn't find template %s", templatesym->s_name); + return; + } + + if (!template_find_field(template, fieldsym, + &onset, &type, &elemtemplatesym)) + { + pd_error(x,"setsize: couldn't find array field %s", fieldsym->s_name); + return; + } + if (type != DT_ARRAY) + { + pd_error(x,"setsize: field %s not of type array", fieldsym->s_name); + return; + } + if (gs->gs_which == GP_ARRAY) w = gp->gp_un.gp_w; + else w = gp->gp_un.gp_scalar->sc_vec; + + if (!(elemtemplate = template_findbyname(elemtemplatesym))) + { + pd_error(x,"element: couldn't find field template %s", + elemtemplatesym->s_name); + return; + } + + elemsize = elemtemplate->t_n * sizeof(t_word); + + array = *(t_array **)(((char *)w) + onset); + + if (elemsize != array->a_elemsize) bug("setsize_gpointer"); + + nitems = array->a_n; + if (newsize < 1) newsize = 1; + if (newsize == nitems) return; + + /* erase the array before resizing it. If we belong to a + scalar it's easy, but if we belong to an element of another + array we have to search back until we get to a scalar to erase. + When graphics updates become queueable this may fall apart... */ + + + if (gs->gs_which == GP_GLIST) + { + if (glist_isvisible(gs->gs_un.gs_glist)) + gobj_vis((t_gobj *)(gp->gp_un.gp_scalar), gs->gs_un.gs_glist, 0); + } + else + { + t_array *owner_array = gs->gs_un.gs_array; + while (owner_array->a_gp.gp_stub->gs_which == GP_ARRAY) + owner_array = owner_array->a_gp.gp_stub->gs_un.gs_array; + if (glist_isvisible(owner_array->a_gp.gp_stub->gs_un.gs_glist)) + gobj_vis((t_gobj *)(owner_array->a_gp.gp_un.gp_scalar), + owner_array->a_gp.gp_stub->gs_un.gs_glist, 0); + } + /* if shrinking, free the scalars that will disappear */ + if (newsize < nitems) + { + char *elem; + int count; + for (elem = ((char *)array->a_vec) + newsize * elemsize, + count = nitems - newsize; count--; elem += elemsize) + word_free((t_word *)elem, elemtemplate); + } + /* resize the array */ + array->a_vec = (char *)resizebytes(array->a_vec, + elemsize * nitems, elemsize * newsize); + array->a_n = newsize; + /* if growing, initialize new scalars */ + if (newsize > nitems) + { + char *elem; + int count; + for (elem = ((char *)array->a_vec) + nitems * elemsize, + count = newsize - nitems; count--; elem += elemsize) + word_init((t_word *)elem, elemtemplate, gp); + } + /* invalidate all gpointers into the array */ + array->a_valid++; + + /* redraw again. */ + if (gs->gs_which == GP_GLIST) + { + if (glist_isvisible(gs->gs_un.gs_glist)) + gobj_vis((t_gobj *)(gp->gp_un.gp_scalar), gs->gs_un.gs_glist, 1); + } + else + { + t_array *owner_array = gs->gs_un.gs_array; + while (owner_array->a_gp.gp_stub->gs_which == GP_ARRAY) + owner_array = owner_array->a_gp.gp_stub->gs_un.gs_array; + if (glist_isvisible(owner_array->a_gp.gp_stub->gs_un.gs_glist)) + gobj_vis((t_gobj *)(owner_array->a_gp.gp_un.gp_scalar), + owner_array->a_gp.gp_stub->gs_un.gs_glist, 1); + } +} + +static void setsize_free(t_setsize *x) +{ + gpointer_unset(&x->x_gp); +} + +static void setsize_setup(void) +{ + setsize_class = class_new(gensym("setsize"), (t_newmethod)setsize_new, + (t_method)setsize_free, sizeof(t_setsize), 0, + A_DEFSYM, A_DEFSYM, A_DEFFLOAT, 0); + class_addfloat(setsize_class, setsize_float); + class_addmethod(setsize_class, (t_method)setsize_set, gensym("set"), + A_SYMBOL, A_SYMBOL, 0); + +} + +/* ---------------------- append ----------------------------- */ + +static t_class *append_class; + +typedef struct _appendvariable +{ + t_symbol *gv_sym; + t_float gv_f; +} t_appendvariable; + +typedef struct _append +{ + t_object x_obj; + t_gpointer x_gp; + t_symbol *x_templatesym; + int x_nin; + t_appendvariable *x_variables; +} t_append; + +static void *append_new(t_symbol *why, int argc, t_atom *argv) +{ + t_append *x = (t_append *)pd_new(append_class); + int varcount, i; + t_atom at, *varvec; + t_appendvariable *sp; + + x->x_templatesym = template_getbindsym(atom_getsymbolarg(0, argc, argv)); + if (argc < 2) + { + varcount = 1; + varvec = &at; + SETSYMBOL(&at, &s_); + } + else varcount = argc - 1, varvec = argv + 1; + x->x_variables + = (t_appendvariable *)getbytes(varcount * sizeof (*x->x_variables)); + x->x_nin = varcount; + for (i = 0, sp = x->x_variables; i < varcount; i++, sp++) + { + sp->gv_sym = atom_getsymbolarg(i, varcount, varvec); + sp->gv_f = 0; + if (i) floatinlet_new(&x->x_obj, &sp->gv_f); + } + pointerinlet_new(&x->x_obj, &x->x_gp); + outlet_new(&x->x_obj, &s_pointer); + gpointer_init(&x->x_gp); + return (x); +} + +static void append_set(t_append *x, t_symbol *templatesym, t_symbol *field) +{ + if (x->x_nin != 1) + pd_error(x, "set: cannot set multiple fields."); + else + { + x->x_templatesym = template_getbindsym(templatesym); + x->x_variables->gv_sym = field; + x->x_variables->gv_f = 0; + } +} + +static void append_float(t_append *x, t_float f) +{ + int nitems = x->x_nin, i; + t_symbol *templatesym = x->x_templatesym; + t_template *template; + t_appendvariable *vp; + t_gpointer *gp = &x->x_gp; + t_gstub *gs = gp->gp_stub; + t_word *vec; + t_scalar *sc, *oldsc; + t_glist *glist; + + if (!templatesym->s_name) + { + pd_error(x, "append: no template supplied"); + return; + } + template = template_findbyname(templatesym); + if (!template) + { + pd_error(x, "append: couldn't find template %s", templatesym->s_name); + return; + } + if (!gs) + { + pd_error(x, "append: no current pointer"); + return; + } + if (gs->gs_which != GP_GLIST) + { + pd_error(x, "append: lists only, not arrays"); + return; + } + glist = gs->gs_un.gs_glist; + if (glist->gl_valid != gp->gp_valid) + { + pd_error(x, "append: stale pointer"); + return; + } + if (!nitems) return; + x->x_variables[0].gv_f = f; + + sc = scalar_new(glist, templatesym); + if (!sc) + { + pd_error(x, "%s: couldn't create scalar", templatesym->s_name); + return; + } + oldsc = gp->gp_un.gp_scalar; + + if (oldsc) + { + sc->sc_gobj.g_next = oldsc->sc_gobj.g_next; + oldsc->sc_gobj.g_next = &sc->sc_gobj; + } + else + { + sc->sc_gobj.g_next = glist->gl_list; + glist->gl_list = &sc->sc_gobj; + } + + gp->gp_un.gp_scalar = sc; + vec = sc->sc_vec; + for (i = 0, vp = x->x_variables; i < nitems; i++, vp++) + { + template_setfloat(template, vp->gv_sym, vec, vp->gv_f, 1); + } + + if (glist_isvisible(glist_getcanvas(glist))) + gobj_vis(&sc->sc_gobj, glist, 1); + /* scalar_redraw(sc, glist); ... have to do 'vis' instead here because + redraw assumes we're already visible??? ... */ + + outlet_pointer(x->x_obj.ob_outlet, gp); +} + +static void append_free(t_append *x) +{ + freebytes(x->x_variables, x->x_nin * sizeof (*x->x_variables)); + gpointer_unset(&x->x_gp); +} + +static void append_setup(void) +{ + append_class = class_new(gensym("append"), (t_newmethod)append_new, + (t_method)append_free, sizeof(t_append), 0, A_GIMME, 0); + class_addfloat(append_class, append_float); + class_addmethod(append_class, (t_method)append_set, gensym("set"), + A_SYMBOL, A_SYMBOL, 0); +} + +/* ----------------- setup function ------------------- */ + +void g_traversal_setup(void) +{ + ptrobj_setup(); + get_setup(); + set_setup(); + elem_setup(); + getsize_setup(); + setsize_setup(); + append_setup(); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_vdial.c b/ports/camomile/source/LibPd/pure-data/src/g_vdial.c new file mode 100644 index 00000000..19008f43 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_vdial.c @@ -0,0 +1,767 @@ +/* Copyright (c) 1997-1999 Miller Puckette. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* vdial.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */ + +/* name change to vradio by MSP (it's a radio button really) and changed to +put out a "float" as in sliders, toggles, etc. */ + +#include +#include +#include +#include +#include "m_pd.h" +#include "g_canvas.h" + +#include "g_all_guis.h" +#include + +/* ------------- vdl gui-vertical radio button ---------------------- */ + +t_widgetbehavior vradio_widgetbehavior; +static t_class *vradio_class, *vradio_old_class; + +/* widget helper functions */ + +void vradio_draw_update(t_gobj *client, t_glist *glist) +{ + t_hradio *x = (t_hradio *)client; + if(glist_isvisible(glist)) + { + t_canvas *canvas=glist_getcanvas(glist); + + sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%06x -outline #%06x\n", + canvas, x, x->x_drawn, + x->x_gui.x_bcol, x->x_gui.x_bcol); + sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%06x -outline #%06x\n", + canvas, x, x->x_on, + x->x_gui.x_fcol, x->x_gui.x_fcol); + x->x_drawn = x->x_on; + } +} + +void vradio_draw_new(t_vradio *x, t_glist *glist) +{ + int n = x->x_number, i, dy = x->x_gui.x_h, s4 = dy / 4; + int yy11b = text_ypix(&x->x_gui.x_obj, glist); + int yy11 = yy11b, yy12 = yy11 + dy; + int yy21 = yy11 + s4, yy22 = yy12 - s4; + int xx11 = text_xpix(&x->x_gui.x_obj, glist), xx12 = xx11 + dy; + int xx21 = xx11 + s4, xx22 = xx12 - s4; + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + for(i = 0; i < n; i++) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -fill #%06x -tags %lxBASE%d\n", + canvas, xx11, yy11, xx12, yy12, IEMGUI_ZOOM(x), + x->x_gui.x_bcol, x, i); + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%06x -outline #%06x -tags %lxBUT%d\n", + canvas, xx21, yy21, xx22, yy22, + (x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol, + (x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol, x, i); + yy11 += dy; + yy12 += dy; + yy21 += dy; + yy22 += dy; + x->x_drawn = x->x_on; + } + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n", + canvas, + xx11, yy11 + IEMGUI_ZOOM(x) - ioh, + xx11 + iow, yy11, + x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n", + canvas, + xx11, yy11b, + xx11 + iow, yy11b - IEMGUI_ZOOM(x) + ioh, + x, 0); + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w -font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n", + canvas, xx11 + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + yy11b + x->x_gui.x_ldy * IEMGUI_ZOOM(x), + (strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""), + x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + x->x_gui.x_lcol, x); +} + +void vradio_draw_move(t_vradio *x, t_glist *glist) +{ + int n = x->x_number, i, dy = x->x_gui.x_h, s4 = dy / 4; + int yy11b = text_ypix(&x->x_gui.x_obj, glist); + int yy11 = yy11b, yy12 = yy11 + dy; + int yy21 = yy11 + s4, yy22 = yy12 - s4; + int xx11 = text_xpix(&x->x_gui.x_obj, glist), xx12 = xx11 + dy; + int xx21 = xx11 + s4, xx22 = xx12 - s4; + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + for(i = 0; i < n; i++) + { + sys_vgui(".x%lx.c coords %lxBASE%d %d %d %d %d\n", + canvas, x, i, xx11, yy11, xx12, yy12); + sys_vgui(".x%lx.c coords %lxBUT%d %d %d %d %d\n", + canvas, x, i, xx21, yy21, xx22, yy22); + yy11 += dy; + yy12 += dy; + yy21 += dy; + yy22 += dy; + } + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n", + canvas, x, 0, + xx11, yy11 + IEMGUI_ZOOM(x) - ioh, + xx11 + iow, yy11); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n", + canvas, x, 0, + xx11, yy11b, + xx11 + iow, yy11b - IEMGUI_ZOOM(x) + ioh); + sys_vgui(".x%lx.c coords %lxLABEL %d %d\n", + canvas, x, xx11 + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + yy11b + x->x_gui.x_ldy * IEMGUI_ZOOM(x)); +} + +void vradio_draw_erase(t_vradio* x, t_glist* glist) +{ + int n = x->x_number, i; + t_canvas *canvas = glist_getcanvas(glist); + + for(i = 0; i < n; i++) + { + sys_vgui(".x%lx.c delete %lxBASE%d\n", canvas, x, i); + sys_vgui(".x%lx.c delete %lxBUT%d\n", canvas, x, i); + } + sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); +} + +void vradio_draw_config(t_vradio* x, t_glist* glist) +{ + int n = x->x_number, i; + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n", + canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol, + strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""); + for(i=0; ix_gui.x_bcol); + sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%06x -outline #%06x\n", canvas, x, i, + (x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol, + (x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol); + } +} + +void vradio_draw_io(t_vradio* x, t_glist* glist, int old_snd_rcv_flags) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n", + canvas, + xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh, + xpos + iow, ypos + x->x_gui.x_h, + x, 0); + /* keep these above outlet */ + if(x->x_on == 0) { + sys_vgui(".x%lx.c raise %lxBUT%d %lxOUT%d\n", canvas, x, x->x_on, x, 0); + sys_vgui(".x%lx.c raise %lxLABEL %lxBUT%d\n", canvas, x, x, x->x_on); + } + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n", + canvas, + xpos, ypos, + xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh, + x, 0); + /* keep these above inlet */ + if(x->x_on == 0) { + sys_vgui(".x%lx.c raise %lxBUT%d %lxIN%d\n", canvas, x, x->x_on, x, 0); + sys_vgui(".x%lx.c raise %lxLABEL %lxBUT%d\n", canvas, x, x, x->x_on); + } + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); +} + +void vradio_draw_select(t_vradio* x, t_glist* glist) +{ + int n = x->x_number, i; + t_canvas *canvas = glist_getcanvas(glist); + + if(x->x_gui.x_fsf.x_selected) + { + for(i = 0; i < n; i++) + { + sys_vgui(".x%lx.c itemconfigure %lxBASE%d -outline #%06x\n", canvas, x, i, + IEM_GUI_COLOR_SELECTED); + } + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + } + else + { + for(i = 0; i < n; i++) + { + sys_vgui(".x%lx.c itemconfigure %lxBASE%d -outline #%06x\n", canvas, x, i, + IEM_GUI_COLOR_NORMAL); + } + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, + x->x_gui.x_lcol); + } +} + +void vradio_draw(t_vradio *x, t_glist *glist, int mode) +{ + if(mode == IEM_GUI_DRAW_MODE_UPDATE) + sys_queuegui(x, glist, vradio_draw_update); + else if(mode == IEM_GUI_DRAW_MODE_MOVE) + vradio_draw_move(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_NEW) + vradio_draw_new(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_SELECT) + vradio_draw_select(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_ERASE) + vradio_draw_erase(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_CONFIG) + vradio_draw_config(x, glist); + else if(mode >= IEM_GUI_DRAW_MODE_IO) + vradio_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO); +} + +/* ------------------------ vdl widgetbehaviour----------------------------- */ + +static void vradio_getrect(t_gobj *z, t_glist *glist, int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_vradio *x = (t_vradio *)z; + + *xp1 = text_xpix(&x->x_gui.x_obj, glist); + *yp1 = text_ypix(&x->x_gui.x_obj, glist); + *xp2 = *xp1 + x->x_gui.x_w; + *yp2 = *yp1 + x->x_gui.x_h * x->x_number; +} + +static void vradio_save(t_gobj *z, t_binbuf *b) +{ + t_vradio *x = (t_vradio *)z; + t_symbol *bflcol[3]; + t_symbol *srl[3]; + + iemgui_save(&x->x_gui, srl, bflcol); + binbuf_addv(b, "ssiisiiiisssiiiisssf", gensym("#X"), gensym("obj"), + (int)x->x_gui.x_obj.te_xpix, + (int)x->x_gui.x_obj.te_ypix, + (pd_class(&x->x_gui.x_obj.ob_pd) == vradio_old_class ? + gensym("vdl") : gensym("vradio")), + x->x_gui.x_w/IEMGUI_ZOOM(x), + x->x_change, iem_symargstoint(&x->x_gui.x_isa), x->x_number, + srl[0], srl[1], srl[2], + x->x_gui.x_ldx, x->x_gui.x_ldy, + iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize, + bflcol[0], bflcol[1], bflcol[2], x->x_fval); + binbuf_addv(b, ";"); +} + +static void vradio_properties(t_gobj *z, t_glist *owner) +{ + t_vradio *x = (t_vradio *)z; + char buf[800]; + t_symbol *srl[3]; + int hchange = -1; + + iemgui_properties(&x->x_gui, srl); + if(pd_class(&x->x_gui.x_obj.ob_pd) == vradio_old_class) + hchange = x->x_change; + sprintf(buf, "pdtk_iemgui_dialog %%s |vradio| \ + ----------dimensions(pix):----------- %d %d size: 0 0 empty \ + empty 0.0 empty 0.0 empty %d \ + %d new-only new&old %d %d number: %d \ + %s %s \ + %s %d %d \ + %d %d \ + #%06x #%06x #%06x\n", + x->x_gui.x_w/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE, + 0,/*no_schedule*/ + hchange, x->x_gui.x_isa.x_loadinit, -1, x->x_number, + srl[0]->s_name, srl[1]->s_name, + srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy, + x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize, + 0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol); + gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf); +} + +static void vradio_dialog(t_vradio *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *srl[3]; + int a = (int)atom_getfloatarg(0, argc, argv); + int chg = (int)atom_getfloatarg(4, argc, argv); + int num = (int)atom_getfloatarg(6, argc, argv); + int sr_flags; + + if(chg != 0) chg = 1; + x->x_change = chg; + sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv); + x->x_gui.x_w = iemgui_clip_size(a) * IEMGUI_ZOOM(x); + x->x_gui.x_h = x->x_gui.x_w; + if(x->x_number != num) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_ERASE); + x->x_number = num; + if(x->x_on >= x->x_number) + { + x->x_on = x->x_number - 1; + x->x_on_old = x->x_on; + } + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_NEW); + } + else + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x); + } +} + +static void vradio_set(t_vradio *x, t_floatarg f) +{ + int i = (int)f; + int old; + + x->x_fval = f; + if(i < 0) + i = 0; + if(i >= x->x_number) + i = x->x_number - 1; + if(x->x_on != x->x_on_old) + { + old = x->x_on_old; + x->x_on_old = x->x_on; + x->x_on = i; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + x->x_on_old = old; + } + else + { + x->x_on = i; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + } +} + +static void vradio_bang(t_vradio *x) +{ + /* compatibility with earlier "vdial" behavior */ + if(pd_class(&x->x_gui.x_obj.ob_pd) == vradio_old_class) + { + if((x->x_change) && (x->x_on != x->x_on_old)) + { + SETFLOAT(x->x_at, (t_float)x->x_on_old); + SETFLOAT(x->x_at+1, 0.0); + outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at); + } + x->x_on_old = x->x_on; + SETFLOAT(x->x_at, (t_float)x->x_on); + SETFLOAT(x->x_at+1, 1.0); + outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at); + } + else + { + float outval = (pd_compatibilitylevel < 46 ? x->x_on : x->x_fval); + outlet_float(x->x_gui.x_obj.ob_outlet, outval); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, outval); + } +} + +static void vradio_fout(t_vradio *x, t_floatarg f) +{ + int i = (int)f; + + x->x_fval = f; + if(i < 0) + i = 0; + if(i >= x->x_number) + i = x->x_number - 1; + + if(pd_class(&x->x_gui.x_obj.ob_pd) == vradio_old_class) + { + /* compatibility with earlier "vdial" behavior */ + if((x->x_change) && (i != x->x_on_old)) + { + SETFLOAT(x->x_at, (t_float)x->x_on_old); + SETFLOAT(x->x_at+1, 0.0); + outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at); + } + if(x->x_on != x->x_on_old) + x->x_on_old = x->x_on; + x->x_on = i; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + x->x_on_old = x->x_on; + SETFLOAT(x->x_at, (t_float)x->x_on); + SETFLOAT(x->x_at+1, 1.0); + outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at); + } + else + { + float outval = (pd_compatibilitylevel < 46 ? i : x->x_fval); + x->x_on_old = x->x_on; + x->x_on = i; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + outlet_float(x->x_gui.x_obj.ob_outlet, outval); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, outval); + } +} + +static void vradio_float(t_vradio *x, t_floatarg f) +{ + int i = (int)f; + + x->x_fval = f; + if(i < 0) + i = 0; + if(i >= x->x_number) + i = x->x_number - 1; + + if(pd_class(&x->x_gui.x_obj.ob_pd) == vradio_old_class) + { + /* compatibility with earlier "vdial" behavior */ + if((x->x_change) && (i != x->x_on_old)) + { + if(x->x_gui.x_fsf.x_put_in2out) + { + SETFLOAT(x->x_at, (t_float)x->x_on_old); + SETFLOAT(x->x_at+1, 0.0); + outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at); + } + } + if(x->x_on != x->x_on_old) + x->x_on_old = x->x_on; + x->x_on = i; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + x->x_on_old = x->x_on; + if(x->x_gui.x_fsf.x_put_in2out) + { + SETFLOAT(x->x_at, (t_float)x->x_on); + SETFLOAT(x->x_at+1, 1.0); + outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at); + } + } + else + { + float outval = (pd_compatibilitylevel < 46 ? i : x->x_fval); + x->x_on_old = x->x_on; + x->x_on = i; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + if(x->x_gui.x_fsf.x_put_in2out) + { + outlet_float(x->x_gui.x_obj.ob_outlet, outval); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, outval); + } + } +} + +static void vradio_click(t_vradio *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + int yy = (int)ypos - text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist); + + vradio_fout(x, (t_float)(yy / x->x_gui.x_h)); +} + +static int vradio_newclick(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + if(doit) + vradio_click((t_vradio *)z, (t_floatarg)xpix, (t_floatarg)ypix, + (t_floatarg)shift, 0, (t_floatarg)alt); + return (1); +} + +static void vradio_loadbang(t_vradio *x, t_floatarg action) +{ + if(action == LB_LOAD && x->x_gui.x_isa.x_loadinit) + vradio_bang(x); +} + +static void vradio_number(t_vradio *x, t_floatarg num) +{ + int n = (int)num; + + if(n < 1) + n = 1; + if(n > IEM_RADIO_MAX) + n = IEM_RADIO_MAX; + if(n != x->x_number) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_ERASE); + x->x_number = n; + if(x->x_on >= x->x_number) + x->x_on = x->x_number - 1; + x->x_on_old = x->x_on; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_NEW); + canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x); + } +} + +static void vradio_size(t_vradio *x, t_symbol *s, int ac, t_atom *av) +{ + x->x_gui.x_w = iemgui_clip_size((int)atom_getfloatarg(0, ac, av)) * IEMGUI_ZOOM(x); + x->x_gui.x_h = x->x_gui.x_w; + iemgui_size((void *)x, &x->x_gui); +} + +static void vradio_delta(t_vradio *x, t_symbol *s, int ac, t_atom *av) +{iemgui_delta((void *)x, &x->x_gui, s, ac, av);} + +static void vradio_pos(t_vradio *x, t_symbol *s, int ac, t_atom *av) +{iemgui_pos((void *)x, &x->x_gui, s, ac, av);} + +static void vradio_color(t_vradio *x, t_symbol *s, int ac, t_atom *av) +{iemgui_color((void *)x, &x->x_gui, s, ac, av);} + +static void vradio_send(t_vradio *x, t_symbol *s) +{iemgui_send(x, &x->x_gui, s);} + +static void vradio_receive(t_vradio *x, t_symbol *s) +{iemgui_receive(x, &x->x_gui, s);} + +static void vradio_label(t_vradio *x, t_symbol *s) +{iemgui_label((void *)x, &x->x_gui, s);} + +static void vradio_label_pos(t_vradio *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);} + +static void vradio_label_font(t_vradio *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);} + +static void vradio_init(t_vradio *x, t_floatarg f) +{x->x_gui.x_isa.x_loadinit = (f == 0.0) ? 0 : 1;} + +static void vradio_double_change(t_vradio *x) +{x->x_change = 1;} + +static void vradio_single_change(t_vradio *x) +{x->x_change = 0;} + +static void *vradio_donew(t_symbol *s, int argc, t_atom *argv, int old) +{ + t_vradio *x = (t_vradio *)pd_new(old ? vradio_old_class : vradio_class); + int a = IEM_GUI_DEFAULTSIZE, on = 0, f = 0; + int ldx = 0, ldy = -8, chg = 1, num = 8; + int fs = 10; + int ftbreak = IEM_BNG_DEFAULTBREAKFLASHTIME, fthold = IEM_BNG_DEFAULTHOLDFLASHTIME; + char str[144]; + float fval = 0; + + x->x_gui.x_bcol = 0xFCFCFC; + x->x_gui.x_fcol = 0x00; + x->x_gui.x_lcol = 0x00; + + if((argc == 15)&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)&&IS_A_FLOAT(argv,2) + &&IS_A_FLOAT(argv,3) + &&(IS_A_SYMBOL(argv,4)||IS_A_FLOAT(argv,4)) + &&(IS_A_SYMBOL(argv,5)||IS_A_FLOAT(argv,5)) + &&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6)) + &&IS_A_FLOAT(argv,7)&&IS_A_FLOAT(argv,8) + &&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10)&&IS_A_FLOAT(argv,14)) + { + a = (int)atom_getfloatarg(0, argc, argv); + chg = (int)atom_getfloatarg(1, argc, argv); + iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(2, argc, argv)); + num = (int)atom_getfloatarg(3, argc, argv); + iemgui_new_getnames(&x->x_gui, 4, argv); + ldx = (int)atom_getfloatarg(7, argc, argv); + ldy = (int)atom_getfloatarg(8, argc, argv); + iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(9, argc, argv)); + fs = (int)atom_getfloatarg(10, argc, argv); + iemgui_all_loadcolors(&x->x_gui, argv+11, argv+12, argv+13); + fval = atom_getfloatarg(14, argc, argv); + } + else iemgui_new_getnames(&x->x_gui, 4, 0); + x->x_gui.x_draw = (t_iemfunptr)vradio_draw; + x->x_gui.x_fsf.x_snd_able = 1; + x->x_gui.x_fsf.x_rcv_able = 1; + x->x_gui.x_glist = (t_glist *)canvas_getcurrent(); + if(!strcmp(x->x_gui.x_snd->s_name, "empty")) + x->x_gui.x_fsf.x_snd_able = 0; + if(!strcmp(x->x_gui.x_rcv->s_name, "empty")) + x->x_gui.x_fsf.x_rcv_able = 0; + if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica"); + else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times"); + else { x->x_gui.x_fsf.x_font_style = 0; + strcpy(x->x_gui.x_font, sys_font); } + if(num < 1) + num = 1; + if(num > IEM_RADIO_MAX) + num = IEM_RADIO_MAX; + x->x_number = num; + x->x_fval = fval; + on = fval; + if(on < 0) + on = 0; + if(on >= x->x_number) + on = x->x_number - 1; + if(x->x_gui.x_isa.x_loadinit) + x->x_on = on; + else + x->x_on = 0; + x->x_on_old = x->x_on; + x->x_change = (chg == 0) ? 0 : 1; + if(x->x_gui.x_fsf.x_rcv_able) + pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + x->x_gui.x_ldx = ldx; + x->x_gui.x_ldy = ldy; + if(fs < 4) + fs = 4; + x->x_gui.x_fontsize = fs; + x->x_gui.x_w = iemgui_clip_size(a); + x->x_gui.x_h = x->x_gui.x_w; + iemgui_verify_snd_ne_rcv(&x->x_gui); + iemgui_newzoom(&x->x_gui); + outlet_new(&x->x_gui.x_obj, &s_list); + return (x); +} + +static void *vradio_new(t_symbol *s, int argc, t_atom *argv) +{ + return (vradio_donew(s, argc, argv, 0)); +} + +static void *vdial_new(t_symbol *s, int argc, t_atom *argv) +{ + return (vradio_donew(s, argc, argv, 1)); +} + +static void vradio_ff(t_vradio *x) +{ + if(x->x_gui.x_fsf.x_rcv_able) + pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + gfxstub_deleteforkey(x); +} + +void g_vradio_setup(void) +{ + vradio_class = class_new(gensym("vradio"), (t_newmethod)vradio_new, + (t_method)vradio_ff, sizeof(t_vradio), 0, A_GIMME, 0); + class_addbang(vradio_class, vradio_bang); + class_addfloat(vradio_class, vradio_float); + class_addmethod(vradio_class, (t_method)vradio_click, + gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(vradio_class, (t_method)vradio_dialog, + gensym("dialog"), A_GIMME, 0); + class_addmethod(vradio_class, (t_method)vradio_loadbang, + gensym("loadbang"), A_DEFFLOAT, 0); + class_addmethod(vradio_class, (t_method)vradio_set, + gensym("set"), A_FLOAT, 0); + class_addmethod(vradio_class, (t_method)vradio_size, + gensym("size"), A_GIMME, 0); + class_addmethod(vradio_class, (t_method)vradio_delta, + gensym("delta"), A_GIMME, 0); + class_addmethod(vradio_class, (t_method)vradio_pos, + gensym("pos"), A_GIMME, 0); + class_addmethod(vradio_class, (t_method)vradio_color, + gensym("color"), A_GIMME, 0); + class_addmethod(vradio_class, (t_method)vradio_send, + gensym("send"), A_DEFSYM, 0); + class_addmethod(vradio_class, (t_method)vradio_receive, + gensym("receive"), A_DEFSYM, 0); + class_addmethod(vradio_class, (t_method)vradio_label, + gensym("label"), A_DEFSYM, 0); + class_addmethod(vradio_class, (t_method)vradio_label_pos, + gensym("label_pos"), A_GIMME, 0); + class_addmethod(vradio_class, (t_method)vradio_label_font, + gensym("label_font"), A_GIMME, 0); + class_addmethod(vradio_class, (t_method)vradio_init, + gensym("init"), A_FLOAT, 0); + class_addmethod(vradio_class, (t_method)vradio_number, + gensym("number"), A_FLOAT, 0); + class_addmethod(vradio_class, (t_method)vradio_single_change, + gensym("single_change"), 0); + class_addmethod(vradio_class, (t_method)vradio_double_change, + gensym("double_change"), 0); + class_addmethod(vradio_class, (t_method)iemgui_zoom, + gensym("zoom"), A_CANT, 0); + vradio_widgetbehavior.w_getrectfn = vradio_getrect; + vradio_widgetbehavior.w_displacefn = iemgui_displace; + vradio_widgetbehavior.w_selectfn = iemgui_select; + vradio_widgetbehavior.w_activatefn = NULL; + vradio_widgetbehavior.w_deletefn = iemgui_delete; + vradio_widgetbehavior.w_visfn = iemgui_vis; + vradio_widgetbehavior.w_clickfn = vradio_newclick; + class_setwidget(vradio_class, &vradio_widgetbehavior); + class_sethelpsymbol(vradio_class, gensym("vradio")); + class_setsavefn(vradio_class, vradio_save); + class_setpropertiesfn(vradio_class, vradio_properties); + + /* obsolete version (0.34-0.35) */ + vradio_old_class = class_new(gensym("vdl"), (t_newmethod)vdial_new, + (t_method)vradio_ff, sizeof(t_vradio), 0, A_GIMME, 0); + class_addbang(vradio_old_class, vradio_bang); + class_addfloat(vradio_old_class, vradio_float); + class_addmethod(vradio_old_class, (t_method)vradio_click, + gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(vradio_old_class, (t_method)vradio_dialog, + gensym("dialog"), A_GIMME, 0); + class_addmethod(vradio_old_class, (t_method)vradio_loadbang, + gensym("loadbang"), 0); + class_addmethod(vradio_old_class, (t_method)vradio_set, + gensym("set"), A_FLOAT, 0); + class_addmethod(vradio_old_class, (t_method)vradio_size, + gensym("size"), A_GIMME, 0); + class_addmethod(vradio_old_class, (t_method)vradio_delta, + gensym("delta"), A_GIMME, 0); + class_addmethod(vradio_old_class, (t_method)vradio_pos, + gensym("pos"), A_GIMME, 0); + class_addmethod(vradio_old_class, (t_method)vradio_color, + gensym("color"), A_GIMME, 0); + class_addmethod(vradio_old_class, (t_method)vradio_send, + gensym("send"), A_DEFSYM, 0); + class_addmethod(vradio_old_class, (t_method)vradio_receive, + gensym("receive"), A_DEFSYM, 0); + class_addmethod(vradio_old_class, (t_method)vradio_label, + gensym("label"), A_DEFSYM, 0); + class_addmethod(vradio_old_class, (t_method)vradio_label_pos, + gensym("label_pos"), A_GIMME, 0); + class_addmethod(vradio_old_class, (t_method)vradio_label_font, + gensym("label_font"), A_GIMME, 0); + class_addmethod(vradio_old_class, (t_method)vradio_init, + gensym("init"), A_FLOAT, 0); + class_addmethod(vradio_old_class, (t_method)vradio_number, + gensym("number"), A_FLOAT, 0); + class_addmethod(vradio_old_class, (t_method)vradio_single_change, + gensym("single_change"), 0); + class_addmethod(vradio_old_class, (t_method)vradio_double_change, + gensym("double_change"), 0); + class_addmethod(vradio_old_class, (t_method)iemgui_zoom, + gensym("zoom"), A_CANT, 0); + class_setwidget(vradio_old_class, &vradio_widgetbehavior); + class_sethelpsymbol(vradio_old_class, gensym("vradio")); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_vslider.c b/ports/camomile/source/LibPd/pure-data/src/g_vslider.c new file mode 100644 index 00000000..e0db6329 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_vslider.c @@ -0,0 +1,690 @@ +/* Copyright (c) 1997-1999 Miller Puckette. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */ +/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */ + +#include +#include +#include +#include +#include "m_pd.h" +#include "g_canvas.h" + +#include "g_all_guis.h" +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +#define TMARGIN 2 +#define BMARGIN 3 + +/* ------------ vsl gui-vertical slider ----------------------- */ + +t_widgetbehavior vslider_widgetbehavior; +static t_class *vslider_class; + +/* widget helper functions */ + +static void vslider_draw_update(t_gobj *client, t_glist *glist) +{ + t_vslider *x = (t_vslider *)client; + if (glist_isvisible(glist)) + { + int r = text_ypix(&x->x_gui.x_obj, glist) + x->x_gui.x_h - + ((x->x_val + 50)/100); + int xpos = text_xpix(&x->x_gui.x_obj, glist); + + sys_vgui(".x%lx.c coords %lxKNOB %d %d %d %d\n", + glist_getcanvas(glist), x, xpos + IEMGUI_ZOOM(x), r, + xpos + x->x_gui.x_w - IEMGUI_ZOOM(x), r); + } +} + +static void vslider_draw_new(t_vslider *x, t_glist *glist) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + int tmargin = TMARGIN * IEMGUI_ZOOM(x), bmargin = BMARGIN * IEMGUI_ZOOM(x); + int r = ypos + x->x_gui.x_h - ((x->x_val + 50)/100); + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -fill #%06x -tags %lxBASE\n", + canvas, xpos, ypos - tmargin, + xpos + x->x_gui.x_w, ypos + x->x_gui.x_h + bmargin, + IEMGUI_ZOOM(x), + x->x_gui.x_bcol, x); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n", + canvas, + xpos, ypos + x->x_gui.x_h + bmargin + IEMGUI_ZOOM(x) - ioh, + xpos + iow, ypos + x->x_gui.x_h + bmargin, + x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n", + canvas, + xpos, ypos - tmargin, + xpos + iow, ypos - tmargin - IEMGUI_ZOOM(x) + ioh, + x, 0); + sys_vgui(".x%lx.c create line %d %d %d %d -width %d -fill #%06x -tags %lxKNOB\n", + canvas, xpos + IEMGUI_ZOOM(x), r, + xpos + x->x_gui.x_w - IEMGUI_ZOOM(x), r, + 1 + 2 * IEMGUI_ZOOM(x), x->x_gui.x_fcol, x); + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \ + -font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n", + canvas, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x), + (strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""), + x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + x->x_gui.x_lcol, x); +} + +static void vslider_draw_move(t_vslider *x, t_glist *glist) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + int tmargin = TMARGIN * IEMGUI_ZOOM(x), bmargin = BMARGIN * IEMGUI_ZOOM(x); + int r = ypos + x->x_gui.x_h - ((x->x_val+ 50)/100); + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n", + canvas, x, + xpos, ypos - tmargin, + xpos + x->x_gui.x_w, ypos + x->x_gui.x_h + bmargin); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n", + canvas, x, 0, + xpos, ypos + x->x_gui.x_h + bmargin + IEMGUI_ZOOM(x) - ioh, + xpos + iow, ypos + x->x_gui.x_h + bmargin); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n", + canvas, x, 0, + xpos, ypos - tmargin, + xpos + iow, ypos - tmargin - IEMGUI_ZOOM(x) + ioh); + sys_vgui(".x%lx.c coords %lxKNOB %d %d %d %d\n", + canvas, x, xpos + IEMGUI_ZOOM(x), r, + xpos + x->x_gui.x_w - IEMGUI_ZOOM(x), r); + sys_vgui(".x%lx.c coords %lxLABEL %d %d\n", + canvas, x, xpos+x->x_gui.x_ldx * IEMGUI_ZOOM(x), + ypos+x->x_gui.x_ldy * IEMGUI_ZOOM(x)); +} + +static void vslider_draw_erase(t_vslider* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c delete %lxBASE\n", canvas, x); + sys_vgui(".x%lx.c delete %lxKNOB\n", canvas, x); + sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x); + if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); +} + +static void vslider_draw_config(t_vslider* x, t_glist* glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n", + canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight, + (x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol), + (strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : "")); + sys_vgui(".x%lx.c itemconfigure %lxKNOB -fill #%06x\n", canvas, + x, x->x_gui.x_fcol); + sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%06x\n", canvas, + x, x->x_gui.x_bcol); +} + +static void vslider_draw_io(t_vslider* x, t_glist* glist, int old_snd_rcv_flags) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + int tmargin = TMARGIN * IEMGUI_ZOOM(x), bmargin = BMARGIN * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n", + canvas, + xpos, ypos + x->x_gui.x_h + bmargin + IEMGUI_ZOOM(x) - ioh, + xpos + iow, ypos + x->x_gui.x_h + bmargin, + x, 0); + /* keep these above outlet */ + sys_vgui(".x%lx.c raise %lxKNOB %lxOUT%d\n", canvas, x, x, 0); + sys_vgui(".x%lx.c raise %lxLABEL %lxKNOB\n", canvas, x, x); + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n", + canvas, + xpos, ypos - tmargin, + xpos + iow, ypos - tmargin - IEMGUI_ZOOM(x) + ioh, + x, 0); + /* keep these above inlet */ + sys_vgui(".x%lx.c raise %lxKNOB %lxIN%d\n", canvas, x, x, 0); + sys_vgui(".x%lx.c raise %lxLABEL %lxKNOB\n", canvas, x, x); + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); +} + +static void vslider_draw_select(t_vslider *x, t_glist *glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + if(x->x_gui.x_fsf.x_selected) + { + sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + } + else + { + sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_NORMAL); + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, x->x_gui.x_lcol); + } +} + +void vslider_draw(t_vslider *x, t_glist *glist, int mode) +{ + if(mode == IEM_GUI_DRAW_MODE_UPDATE) + sys_queuegui(x, glist, vslider_draw_update); + else if(mode == IEM_GUI_DRAW_MODE_MOVE) + vslider_draw_move(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_NEW) + vslider_draw_new(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_SELECT) + vslider_draw_select(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_ERASE) + vslider_draw_erase(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_CONFIG) + vslider_draw_config(x, glist); + else if(mode >= IEM_GUI_DRAW_MODE_IO) + vslider_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO); +} + +/* ------------------------ vsl widgetbehaviour----------------------------- */ + + +static void vslider_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_vslider* x = (t_vslider*)z; + + *xp1 = text_xpix(&x->x_gui.x_obj, glist); + *yp1 = text_ypix(&x->x_gui.x_obj, glist) - TMARGIN*glist_getzoom(glist); + *xp2 = *xp1 + x->x_gui.x_w; + *yp2 = *yp1 + x->x_gui.x_h + (TMARGIN + BMARGIN)*glist_getzoom(glist); +} + +static void vslider_save(t_gobj *z, t_binbuf *b) +{ + t_vslider *x = (t_vslider *)z; + t_symbol *bflcol[3]; + t_symbol *srl[3]; + + iemgui_save(&x->x_gui, srl, bflcol); + binbuf_addv(b, "ssiisiiffiisssiiiisssii", gensym("#X"), gensym("obj"), + (int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix, + gensym("vsl"), x->x_gui.x_w/IEMGUI_ZOOM(x), x->x_gui.x_h/IEMGUI_ZOOM(x), + (t_float)x->x_min, (t_float)x->x_max, + x->x_lin0_log1, iem_symargstoint(&x->x_gui.x_isa), + srl[0], srl[1], srl[2], + x->x_gui.x_ldx, x->x_gui.x_ldy, + iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize, + bflcol[0], bflcol[1], bflcol[2], + x->x_val, x->x_steady); + binbuf_addv(b, ";"); +} + +void vslider_check_height(t_vslider *x, int h) +{ + if(h < IEM_SL_MINSIZE * IEMGUI_ZOOM(x)) + h = IEM_SL_MINSIZE * IEMGUI_ZOOM(x); + x->x_gui.x_h = h; + if(x->x_val > (x->x_gui.x_h*100 - 100)) + { + x->x_pos = x->x_gui.x_h*100 - 100; + x->x_val = x->x_pos; + } + if(x->x_lin0_log1) + x->x_k = log(x->x_max / x->x_min) / (double)(x->x_gui.x_h/IEMGUI_ZOOM(x) - 1); + else + x->x_k = (x->x_max - x->x_min) / (double)(x->x_gui.x_h/IEMGUI_ZOOM(x) - 1); +} + +void vslider_check_minmax(t_vslider *x, double min, double max) +{ + if(x->x_lin0_log1) + { + if((min == 0.0) && (max == 0.0)) + max = 1.0; + if(max > 0.0) + { + if(min <= 0.0) + min = 0.01 * max; + } + else + { + if(min > 0.0) + max = 0.01 * min; + } + } + x->x_min = min; + x->x_max = max; + if(x->x_lin0_log1) + x->x_k = log(x->x_max/x->x_min) / (double)(x->x_gui.x_h/IEMGUI_ZOOM(x) - 1); + else + x->x_k = (x->x_max - x->x_min) / (double)(x->x_gui.x_h/IEMGUI_ZOOM(x) - 1); +} + +static void vslider_properties(t_gobj *z, t_glist *owner) +{ + t_vslider *x = (t_vslider *)z; + char buf[800]; + t_symbol *srl[3]; + + iemgui_properties(&x->x_gui, srl); + + sprintf(buf, "pdtk_iemgui_dialog %%s |vsl| \ + --------dimensions(pix)(pix):-------- %d %d width: %d %d height: \ + -----------output-range:----------- %g bottom: %g top: %d \ + %d lin log %d %d empty %d \ + %s %s \ + %s %d %d \ + %d %d \ + #%06x #%06x #%06x\n", + x->x_gui.x_w/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE, x->x_gui.x_h/IEMGUI_ZOOM(x), IEM_SL_MINSIZE, + x->x_min, x->x_max, 0,/*no_schedule*/ + x->x_lin0_log1, x->x_gui.x_isa.x_loadinit, x->x_steady, -1,/*no multi, but iem-characteristic*/ + srl[0]->s_name, srl[1]->s_name, + srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy, + x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize, + 0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol); + gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf); +} + + /* compute numeric value (fval) from pixel location (val) and range */ +static t_float vslider_getfval(t_vslider *x) +{ + t_float fval; + int zoomval = (x->x_gui.x_fsf.x_finemoved) ? + x->x_val/IEMGUI_ZOOM(x) : (x->x_val / (100*IEMGUI_ZOOM(x))) * 100; + + if (x->x_lin0_log1) + fval = x->x_min * exp(x->x_k * (double)(zoomval) * 0.01); + else fval = (double)(zoomval) * 0.01 * x->x_k + x->x_min; + if ((fval < 1.0e-10) && (fval > -1.0e-10)) + fval = 0.0; + return (fval); +} + +static void vslider_bang(t_vslider *x) +{ + double out; + + if (pd_compatibilitylevel < 46) + out = vslider_getfval(x); + else out = x->x_fval; + outlet_float(x->x_gui.x_obj.ob_outlet, out); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, out); +} + +static void vslider_dialog(t_vslider *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *srl[3]; + int w = (int)atom_getfloatarg(0, argc, argv); + int h = (int)atom_getfloatarg(1, argc, argv) * IEMGUI_ZOOM(x); + double min = (double)atom_getfloatarg(2, argc, argv); + double max = (double)atom_getfloatarg(3, argc, argv); + int lilo = (int)atom_getfloatarg(4, argc, argv); + int steady = (int)atom_getfloatarg(17, argc, argv); + int sr_flags; + + if(lilo != 0) lilo = 1; + x->x_lin0_log1 = lilo; + if(steady) + x->x_steady = 1; + else + x->x_steady = 0; + sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv); + x->x_gui.x_w = iemgui_clip_size(w) * IEMGUI_ZOOM(x); + vslider_check_height(x, h); + vslider_check_minmax(x, min, max); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x); +} + +static void vslider_motion(t_vslider *x, t_floatarg dx, t_floatarg dy) +{ + int old = x->x_val; + + if(x->x_gui.x_fsf.x_finemoved) + x->x_pos -= (int)dy; + else + x->x_pos -= 100 * (int)dy; + x->x_val = x->x_pos; + if(x->x_val > (100*x->x_gui.x_h - 100)) + { + x->x_val = 100*x->x_gui.x_h - 100; + x->x_pos += 50; + x->x_pos -= x->x_pos % 100; + } + if(x->x_val < 0) + { + x->x_val = 0; + x->x_pos -= 50; + x->x_pos -= x->x_pos % 100; + } + x->x_fval = vslider_getfval(x); + if (old != x->x_val) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + vslider_bang(x); + } +} + +static void vslider_click(t_vslider *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + if(!x->x_steady) + x->x_val = (int)(100.0 * (x->x_gui.x_h + text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist) - ypos)); + if(x->x_val > (100*x->x_gui.x_h - 100)) + x->x_val = 100*x->x_gui.x_h - 100; + if(x->x_val < 0) + x->x_val = 0; + x->x_fval = vslider_getfval(x); + x->x_pos = x->x_val; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + vslider_bang(x); + glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, + (t_glistmotionfn)vslider_motion, 0, xpos, ypos); +} + +static int vslider_newclick(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_vslider* x = (t_vslider *)z; + + if(doit) + { + vslider_click(x, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, + 0, (t_floatarg)alt); + if(shift) + x->x_gui.x_fsf.x_finemoved = 1; + else + x->x_gui.x_fsf.x_finemoved = 0; + } + return (1); +} + +static void vslider_set(t_vslider *x, t_floatarg f) +{ + int old = x->x_val; + double g; + + x->x_fval = f; + if (x->x_min > x->x_max) + { + if(f > x->x_min) + f = x->x_min; + if(f < x->x_max) + f = x->x_max; + } + else + { + if(f > x->x_max) + f = x->x_max; + if(f < x->x_min) + f = x->x_min; + } + if(x->x_lin0_log1) + g = log(f/x->x_min) / x->x_k; + else + g = (f - x->x_min) / x->x_k; + x->x_val = IEMGUI_ZOOM(x) * (int)(100.0*g + 0.49999); + x->x_pos = x->x_val; + if(x->x_val != old) + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); +} + +static void vslider_float(t_vslider *x, t_floatarg f) +{ + vslider_set(x, f); + if(x->x_gui.x_fsf.x_put_in2out) + vslider_bang(x); +} + +static void vslider_size(t_vslider *x, t_symbol *s, int ac, t_atom *av) +{ + x->x_gui.x_w = iemgui_clip_size((int)atom_getfloatarg(0, ac, av))*IEMGUI_ZOOM(x); + if(ac > 1) + vslider_check_height(x, (int)atom_getfloatarg(1, ac, av)*IEMGUI_ZOOM(x)); + iemgui_size((void *)x, &x->x_gui); +} + +static void vslider_delta(t_vslider *x, t_symbol *s, int ac, t_atom *av) +{iemgui_delta((void *)x, &x->x_gui, s, ac, av);} + +static void vslider_pos(t_vslider *x, t_symbol *s, int ac, t_atom *av) +{iemgui_pos((void *)x, &x->x_gui, s, ac, av);} + +static void vslider_range(t_vslider *x, t_symbol *s, int ac, t_atom *av) +{ + vslider_check_minmax(x, (double)atom_getfloatarg(0, ac, av), + (double)atom_getfloatarg(1, ac, av)); +} + +static void vslider_color(t_vslider *x, t_symbol *s, int ac, t_atom *av) +{iemgui_color((void *)x, &x->x_gui, s, ac, av);} + +static void vslider_send(t_vslider *x, t_symbol *s) +{iemgui_send(x, &x->x_gui, s);} + +static void vslider_receive(t_vslider *x, t_symbol *s) +{iemgui_receive(x, &x->x_gui, s);} + +static void vslider_label(t_vslider *x, t_symbol *s) +{iemgui_label((void *)x, &x->x_gui, s);} + +static void vslider_label_pos(t_vslider *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);} + +static void vslider_label_font(t_vslider *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);} + +static void vslider_log(t_vslider *x) +{ + x->x_lin0_log1 = 1; + vslider_check_minmax(x, x->x_min, x->x_max); +} + +static void vslider_lin(t_vslider *x) +{ + x->x_lin0_log1 = 0; + x->x_k = (x->x_max - x->x_min) / (double)(x->x_gui.x_h/IEMGUI_ZOOM(x) - 1); +} + +static void vslider_init(t_vslider *x, t_floatarg f) +{ + x->x_gui.x_isa.x_loadinit = (f == 0.0) ? 0 : 1; +} + +static void vslider_steady(t_vslider *x, t_floatarg f) +{ + x->x_steady = (f == 0.0) ? 0 : 1; +} + +static void vslider_zoom(t_vslider *x, t_floatarg f) +{ + /* scale current pixel value */ + x->x_val = (IEMGUI_ZOOM(x) == 2 ? (x->x_val)/2 : (x->x_val)*2); + x->x_pos = x->x_val; + iemgui_zoom(&x->x_gui, f); +} + +static void vslider_loadbang(t_vslider *x, t_floatarg action) +{ + if (action == LB_LOAD && x->x_gui.x_isa.x_loadinit) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + vslider_bang(x); + } +} + +static void *vslider_new(t_symbol *s, int argc, t_atom *argv) +{ + t_vslider *x = (t_vslider *)pd_new(vslider_class); + int w = IEM_GUI_DEFAULTSIZE, h = IEM_SL_DEFAULTSIZE; + int lilo = 0, f = 0, ldx = 0, ldy = -9; + int fs = 10, steady = 1; + double min = 0.0, max = (double)(IEM_SL_DEFAULTSIZE-1); + char str[144]; + float v = 0; + + iem_inttosymargs(&x->x_gui.x_isa, 0); + iem_inttofstyle(&x->x_gui.x_fsf, 0); + + x->x_gui.x_bcol = 0xFCFCFC; + x->x_gui.x_fcol = 0x00; + x->x_gui.x_lcol = 0x00; + + if(((argc == 17)||(argc == 18))&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1) + &&IS_A_FLOAT(argv,2)&&IS_A_FLOAT(argv,3) + &&IS_A_FLOAT(argv,4)&&IS_A_FLOAT(argv,5) + &&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6)) + &&(IS_A_SYMBOL(argv,7)||IS_A_FLOAT(argv,7)) + &&(IS_A_SYMBOL(argv,8)||IS_A_FLOAT(argv,8)) + &&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10) + &&IS_A_FLOAT(argv,11)&&IS_A_FLOAT(argv,12)&&IS_A_FLOAT(argv,16)) + { + w = (int)atom_getfloatarg(0, argc, argv); + h = (int)atom_getfloatarg(1, argc, argv); + min = (double)atom_getfloatarg(2, argc, argv); + max = (double)atom_getfloatarg(3, argc, argv); + lilo = (int)atom_getfloatarg(4, argc, argv); + iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(5, argc, argv)); + iemgui_new_getnames(&x->x_gui, 6, argv); + ldx = (int)atom_getfloatarg(9, argc, argv); + ldy = (int)atom_getfloatarg(10, argc, argv); + iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(11, argc, argv)); + fs = (int)atom_getfloatarg(12, argc, argv); + iemgui_all_loadcolors(&x->x_gui, argv+13, argv+14, argv+15); + v = atom_getfloatarg(16, argc, argv); + } + else iemgui_new_getnames(&x->x_gui, 6, 0); + if((argc == 18)&&IS_A_FLOAT(argv,17)) + steady = (int)atom_getfloatarg(17, argc, argv); + x->x_gui.x_draw = (t_iemfunptr)vslider_draw; + x->x_gui.x_fsf.x_snd_able = 1; + x->x_gui.x_fsf.x_rcv_able = 1; + x->x_gui.x_glist = (t_glist *)canvas_getcurrent(); + if (x->x_gui.x_isa.x_loadinit) + x->x_val = v; + else x->x_val = 0; + x->x_pos = x->x_val; + if(lilo != 0) lilo = 1; + x->x_lin0_log1 = lilo; + if(steady != 0) steady = 1; + x->x_steady = steady; + if(!strcmp(x->x_gui.x_snd->s_name, "empty")) x->x_gui.x_fsf.x_snd_able = 0; + if(!strcmp(x->x_gui.x_rcv->s_name, "empty")) x->x_gui.x_fsf.x_rcv_able = 0; + if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica"); + else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times"); + else { x->x_gui.x_fsf.x_font_style = 0; + strcpy(x->x_gui.x_font, sys_font); } + if(x->x_gui.x_fsf.x_rcv_able) pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + x->x_gui.x_ldx = ldx; + x->x_gui.x_ldy = ldy; + if(fs < 4) + fs = 4; + x->x_gui.x_fontsize = fs; + x->x_gui.x_w = iemgui_clip_size(w); + vslider_check_height(x, h); + iemgui_verify_snd_ne_rcv(&x->x_gui); + iemgui_newzoom(&x->x_gui); + vslider_check_minmax(x, min, max); + outlet_new(&x->x_gui.x_obj, &s_float); + x->x_fval = vslider_getfval(x); + return (x); +} + +static void vslider_free(t_vslider *x) +{ + if(x->x_gui.x_fsf.x_rcv_able) + pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + gfxstub_deleteforkey(x); +} + +void g_vslider_setup(void) +{ + vslider_class = class_new(gensym("vsl"), (t_newmethod)vslider_new, + (t_method)vslider_free, sizeof(t_vslider), 0, A_GIMME, 0); + class_addcreator((t_newmethod)vslider_new, gensym("vslider"), A_GIMME, 0); + class_addbang(vslider_class,vslider_bang); + class_addfloat(vslider_class,vslider_float); + class_addmethod(vslider_class, (t_method)vslider_click, + gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(vslider_class, (t_method)vslider_motion, + gensym("motion"), A_FLOAT, A_FLOAT, 0); + class_addmethod(vslider_class, (t_method)vslider_dialog, + gensym("dialog"), A_GIMME, 0); + class_addmethod(vslider_class, (t_method)vslider_loadbang, + gensym("loadbang"), A_DEFFLOAT, 0); + class_addmethod(vslider_class, (t_method)vslider_set, + gensym("set"), A_FLOAT, 0); + class_addmethod(vslider_class, (t_method)vslider_size, + gensym("size"), A_GIMME, 0); + class_addmethod(vslider_class, (t_method)vslider_delta, + gensym("delta"), A_GIMME, 0); + class_addmethod(vslider_class, (t_method)vslider_pos, + gensym("pos"), A_GIMME, 0); + class_addmethod(vslider_class, (t_method)vslider_range, + gensym("range"), A_GIMME, 0); + class_addmethod(vslider_class, (t_method)vslider_color, + gensym("color"), A_GIMME, 0); + class_addmethod(vslider_class, (t_method)vslider_send, + gensym("send"), A_DEFSYM, 0); + class_addmethod(vslider_class, (t_method)vslider_receive, + gensym("receive"), A_DEFSYM, 0); + class_addmethod(vslider_class, (t_method)vslider_label, + gensym("label"), A_DEFSYM, 0); + class_addmethod(vslider_class, (t_method)vslider_label_pos, + gensym("label_pos"), A_GIMME, 0); + class_addmethod(vslider_class, (t_method)vslider_label_font, + gensym("label_font"), A_GIMME, 0); + class_addmethod(vslider_class, (t_method)vslider_log, + gensym("log"), 0); + class_addmethod(vslider_class, (t_method)vslider_lin, + gensym("lin"), 0); + class_addmethod(vslider_class, (t_method)vslider_init, + gensym("init"), A_FLOAT, 0); + class_addmethod(vslider_class, (t_method)vslider_steady, + gensym("steady"), A_FLOAT, 0); + class_addmethod(vslider_class, (t_method)vslider_zoom, + gensym("zoom"), A_CANT, 0); + vslider_widgetbehavior.w_getrectfn = vslider_getrect; + vslider_widgetbehavior.w_displacefn = iemgui_displace; + vslider_widgetbehavior.w_selectfn = iemgui_select; + vslider_widgetbehavior.w_activatefn = NULL; + vslider_widgetbehavior.w_deletefn = iemgui_delete; + vslider_widgetbehavior.w_visfn = iemgui_vis; + vslider_widgetbehavior.w_clickfn = vslider_newclick; + class_setwidget(vslider_class, &vslider_widgetbehavior); + class_sethelpsymbol(vslider_class, gensym("vslider")); + class_setsavefn(vslider_class, vslider_save); + class_setpropertiesfn(vslider_class, vslider_properties); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/g_vumeter.c b/ports/camomile/source/LibPd/pure-data/src/g_vumeter.c new file mode 100644 index 00000000..cb7303e3 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/g_vumeter.c @@ -0,0 +1,773 @@ +/* Copyright (c) 1997-1999 Miller Puckette. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */ +/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */ + + +#include +#include +#include +#include +#include "m_pd.h" +#include "g_canvas.h" + +#include "g_all_guis.h" +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +#define HMARGIN 1 +#define VMARGIN 2 +#define PEAKHEIGHT 10 + +/* ----- vu gui-peak- & rms- vu-meter-display ---------- */ + +t_widgetbehavior vu_widgetbehavior; +static t_class *vu_class; + +/* widget helper functions */ + +static void vu_update_rms(t_vu *x, t_glist *glist) +{ + if(glist_isvisible(glist)) + { + int w4 = x->x_gui.x_w / 4, off = text_ypix(&x->x_gui.x_obj, glist) - IEMGUI_ZOOM(x); + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int quad1 = xpos + w4 - IEMGUI_ZOOM(x), quad3 = xpos + x->x_gui.x_w - w4 + IEMGUI_ZOOM(x); + + sys_vgui(".x%lx.c coords %lxRCOVER %d %d %d %d\n", + glist_getcanvas(glist), x, quad1, off, quad3, + off + (x->x_led_size+1)*IEMGUI_ZOOM(x)*(IEM_VU_STEPS-x->x_rms)); + } +} + +static void vu_update_peak(t_vu *x, t_glist *glist) +{ + t_canvas *canvas = glist_getcanvas(glist); + + if(glist_isvisible(glist)) + { + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + + if(x->x_peak) + { + int i = iemgui_vu_col[x->x_peak]; + int j = ypos + + (x->x_led_size+1)*IEMGUI_ZOOM(x)*(IEM_VU_STEPS+1-x->x_peak) - + (x->x_led_size+1)*IEMGUI_ZOOM(x)/2; + + sys_vgui(".x%lx.c coords %lxPLED %d %d %d %d\n", canvas, x, + xpos, j, xpos + x->x_gui.x_w + IEMGUI_ZOOM(x), j); + sys_vgui(".x%lx.c itemconfigure %lxPLED -fill #%06x\n", canvas, x, + iemgui_color_hex[i]); + } + else + { + int mid = xpos + x->x_gui.x_w/2; + int pkh = PEAKHEIGHT * IEMGUI_ZOOM(x); + + sys_vgui(".x%lx.c itemconfigure %lxPLED -fill #%06x\n", + canvas, x, x->x_gui.x_bcol); + sys_vgui(".x%lx.c coords %lxPLED %d %d %d %d\n", + canvas, x, mid, ypos + pkh, mid, ypos + pkh); + } + } +} + +static void vu_draw_update(t_gobj *client, t_glist *glist) +{ + t_vu *x = (t_vu *)client; + if (x->x_updaterms) + { + vu_update_rms(x, glist); + x->x_updaterms = 0; + } + if (x->x_updatepeak) + { + vu_update_peak(x, glist); + x->x_updatepeak = 0; + } +} + +static void vu_draw_new(t_vu *x, t_glist *glist) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int hmargin = HMARGIN * IEMGUI_ZOOM(x), vmargin = VMARGIN * IEMGUI_ZOOM(x); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + int w4 = x->x_gui.x_w/4, mid = xpos + x->x_gui.x_w/2, + quad1 = xpos + w4 + IEMGUI_ZOOM(x); + int quad3 = xpos + x->x_gui.x_w - w4, + end = xpos + x->x_gui.x_w + 4*IEMGUI_ZOOM(x); + int k1 = (x->x_led_size+1)*IEMGUI_ZOOM(x), k2 = IEM_VU_STEPS+1, k3 = k1/2; + int led_col, yyy, i, k4 = ypos - k3; + int ledw = x->x_led_size * IEMGUI_ZOOM(x); + int fs = x->x_gui.x_fontsize * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -fill #%06x -tags %lxBASE\n", + canvas, xpos - hmargin, ypos - vmargin, + xpos+x->x_gui.x_w + hmargin, + ypos+x->x_gui.x_h + vmargin, IEMGUI_ZOOM(x), x->x_gui.x_bcol, x); + for(i = 1; i <= IEM_VU_STEPS; i++) + { + led_col = iemgui_vu_col[i]; + yyy = k4 + k1*(k2-i); + sys_vgui(".x%lx.c create line %d %d %d %d -width %d -fill #%06x -tags %lxRLED%d\n", + canvas, quad1, yyy, quad3, yyy, ledw, + iemgui_color_hex[led_col], x, i); + if(((i+2) & 3) && (x->x_scale)) + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \ + -font {{%s} -%d %s} -fill #%06x -tags %lxSCALE%d\n", + canvas, end, yyy + k3, iemgui_vu_scale_str[i], + x->x_gui.x_font, fs, + sys_fontweight, x->x_gui.x_lcol, x, i); + } + if(x->x_scale) + { + i = IEM_VU_STEPS + 1; + yyy = k4 + k1 * (k2 - i); + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \ + -font {{%s} -%d %s} -fill #%06x -tags %lxSCALE%d\n", + canvas, end, yyy + k3, iemgui_vu_scale_str[i], + x->x_gui.x_font, fs, + sys_fontweight, x->x_gui.x_lcol, x, i); + } + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%06x -outline #%06x -tags %lxRCOVER\n", + canvas, quad1 - IEMGUI_ZOOM(x), ypos - IEMGUI_ZOOM(x), quad3 + IEMGUI_ZOOM(x), + ypos - IEMGUI_ZOOM(x) + k1*IEM_VU_STEPS, x->x_gui.x_bcol, x->x_gui.x_bcol, x); + sys_vgui(".x%lx.c create line %d %d %d %d -width %d -fill #%06x -tags %lxPLED\n", + canvas, mid, ypos + PEAKHEIGHT * IEMGUI_ZOOM(x), + mid, ypos + PEAKHEIGHT * IEMGUI_ZOOM(x), + (x->x_led_size+1)*IEMGUI_ZOOM(x), x->x_gui.x_bcol, x); + if(!x->x_gui.x_fsf.x_snd_able) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n", + canvas, + xpos - hmargin, ypos + x->x_gui.x_h + vmargin + IEMGUI_ZOOM(x) - ioh, + xpos - hmargin + iow, ypos + x->x_gui.x_h + vmargin, + x, 0); + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]x\n", + canvas, + xpos + x->x_gui.x_w + hmargin - iow, ypos + x->x_gui.x_h + vmargin + IEMGUI_ZOOM(x) - ioh, + xpos + x->x_gui.x_w + hmargin, ypos + x->x_gui.x_h + vmargin, + x, 1); + } + if(!x->x_gui.x_fsf.x_rcv_able) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n", + canvas, + xpos - hmargin, ypos - vmargin, + xpos - hmargin + iow, ypos - vmargin - IEMGUI_ZOOM(x) + ioh, + x, 0); + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n", + canvas, + xpos + x->x_gui.x_w + hmargin - iow, ypos - vmargin, + xpos + x->x_gui.x_w + hmargin, ypos - vmargin - IEMGUI_ZOOM(x) + ioh, + x, 1); + } + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \ + -font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n", + canvas, xpos+x->x_gui.x_ldx * IEMGUI_ZOOM(x), ypos+x->x_gui.x_ldy * IEMGUI_ZOOM(x), + (strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""), + x->x_gui.x_font, fs, sys_fontweight, + x->x_gui.x_lcol, x); + x->x_updaterms = x->x_updatepeak = 1; + sys_queuegui(x, x->x_gui.x_glist, vu_draw_update); +} + +static void vu_draw_move(t_vu *x, t_glist *glist) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int hmargin = HMARGIN * IEMGUI_ZOOM(x), vmargin = VMARGIN * IEMGUI_ZOOM(x); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + int w4 = x->x_gui.x_w/4, quad1 = xpos + w4 + IEMGUI_ZOOM(x); + int quad3 = xpos + x->x_gui.x_w - w4, + end = xpos + x->x_gui.x_w + 4*IEMGUI_ZOOM(x); + int k1 = (x->x_led_size+1)*IEMGUI_ZOOM(x), k2 = IEM_VU_STEPS+1, k3 = k1/2; + int yyy, i, k4 = ypos - k3; + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n", + canvas, x, xpos - hmargin, ypos - vmargin, + xpos + x->x_gui.x_w + hmargin, ypos + x->x_gui.x_h + vmargin); + for(i = 1; i <= IEM_VU_STEPS; i++) + { + yyy = k4 + k1 * (k2 - i); + sys_vgui(".x%lx.c coords %lxRLED%d %d %d %d %d\n", + canvas, x, i, quad1, yyy, quad3, yyy); + if(((i+2) & 3) && (x->x_scale)) + sys_vgui(".x%lx.c coords %lxSCALE%d %d %d\n", + canvas, x, i, end, yyy + k3); + } + if(x->x_scale) + { + i = IEM_VU_STEPS + 1; + yyy = k4 + k1 * (k2 - i); + sys_vgui(".x%lx.c coords %lxSCALE%d %d %d\n", + canvas, x, i, end, yyy + k3); + } + x->x_updaterms = x->x_updatepeak = 1; + sys_queuegui(x, glist, vu_draw_update); + sys_vgui(".x%lx.c coords %lxLABEL %d %d\n", + canvas, x, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x), + ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x)); + if(!x->x_gui.x_fsf.x_snd_able) + { + sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n", + canvas, x, 0, + xpos - hmargin, ypos + x->x_gui.x_h + vmargin + IEMGUI_ZOOM(x) - ioh, + xpos - hmargin + iow, ypos + x->x_gui.x_h + vmargin); + sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n", + canvas, x, 1, + xpos + x->x_gui.x_w + hmargin - iow, ypos + x->x_gui.x_h + vmargin + IEMGUI_ZOOM(x) - ioh, + xpos + x->x_gui.x_w + hmargin, ypos + x->x_gui.x_h + vmargin); + } + if(!x->x_gui.x_fsf.x_rcv_able) + { + sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n", + canvas, x, 0, + xpos - hmargin, ypos - vmargin, + xpos - hmargin + iow, ypos - vmargin - IEMGUI_ZOOM(x) + ioh); + sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n", + canvas, x, 1, + xpos + x->x_gui.x_w + hmargin - iow, ypos - vmargin, + xpos + x->x_gui.x_w + hmargin, ypos - vmargin - IEMGUI_ZOOM(x) + ioh); + } +} + +static void vu_draw_erase(t_vu* x,t_glist* glist) +{ + int i; + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c delete %lxBASE\n", canvas, x); + for(i = 1; i <= IEM_VU_STEPS; i++) + { + sys_vgui(".x%lx.c delete %lxRLED%d\n", canvas, x, i); + if(((i+2) & 3) && (x->x_scale)) + sys_vgui(".x%lx.c delete %lxSCALE%d\n", canvas, x, i); + } + if(x->x_scale) + { + i = IEM_VU_STEPS + 1; + sys_vgui(".x%lx.c delete %lxSCALE%d\n", canvas, x, i); + } + sys_vgui(".x%lx.c delete %lxPLED\n", canvas, x); + sys_vgui(".x%lx.c delete %lxRCOVER\n", canvas, x); + sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x); + if(!x->x_gui.x_fsf.x_snd_able) + { + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 1); + } + if(!x->x_gui.x_fsf.x_rcv_able) + { + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 1); + } +} + +static void vu_draw_config(t_vu* x, t_glist* glist) +{ + int i; + int ledw = x->x_led_size * IEMGUI_ZOOM(x); + int fs = x->x_gui.x_fontsize * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%06x\n", canvas, x, x->x_gui.x_bcol); + for(i = 1; i <= IEM_VU_STEPS; i++) + { + sys_vgui(".x%lx.c itemconfigure %lxRLED%d -width %d\n", canvas, x, i, ledw); + if(((i+2) & 3) && (x->x_scale)) + sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -text {%s} -font {{%s} -%d %s} -fill #%06x\n", + canvas, x, i, iemgui_vu_scale_str[i], x->x_gui.x_font, + fs, sys_fontweight, + x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol); + } + if(x->x_scale) + { + i = IEM_VU_STEPS + 1; + sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -text {%s} -font {{%s} -%d %s} -fill #%06x\n", + canvas, x, i, iemgui_vu_scale_str[i], x->x_gui.x_font, + fs, sys_fontweight, + x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol); + } + sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n", + canvas, x, x->x_gui.x_font, fs, sys_fontweight, + x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol, + strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""); + + sys_vgui(".x%lx.c itemconfigure %lxRCOVER -fill #%06x -outline #%06x\n", canvas, + x, x->x_gui.x_bcol, x->x_gui.x_bcol); + sys_vgui(".x%lx.c itemconfigure %lxPLED -width %d\n", canvas, x, ledw); +} + +static void vu_draw_io(t_vu* x, t_glist* glist, int old_snd_rcv_flags) +{ + int xpos = text_xpix(&x->x_gui.x_obj, glist); + int ypos = text_ypix(&x->x_gui.x_obj, glist); + int hmargin = HMARGIN * IEMGUI_ZOOM(x), vmargin = VMARGIN * IEMGUI_ZOOM(x); + int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(glist); + + if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n", + canvas, + xpos - hmargin, ypos + x->x_gui.x_h + vmargin + IEMGUI_ZOOM(x) - ioh, + xpos - hmargin + iow, ypos + x->x_gui.x_h + vmargin, + x, 0); + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n", + canvas, + xpos + x->x_gui.x_w + hmargin - iow, ypos + x->x_gui.x_h + vmargin + IEMGUI_ZOOM(x) - ioh, + xpos + x->x_gui.x_w + hmargin, ypos + x->x_gui.x_h + vmargin, + x, 1); + /* keep above outlets */ + sys_vgui(".x%lx.c raise %lxLABEL %lxOUT%d\n", canvas, x, x, 1); + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able) + { + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0); + sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 1); + } + if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able) + { + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n", + canvas, + xpos - hmargin, ypos - vmargin, + xpos - hmargin + iow, ypos - vmargin - IEMGUI_ZOOM(x) + ioh, + x, 0); + sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n", + canvas, + xpos + x->x_gui.x_w + hmargin - iow, ypos - vmargin, + xpos + x->x_gui.x_w + hmargin, ypos - vmargin - IEMGUI_ZOOM(x) + ioh, + x, 1); + /* keep above inlets */ + sys_vgui(".x%lx.c raise %lxLABEL %lxIN%d\n", canvas, x, x, 1); + } + if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able) + { + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0); + sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 1); + } +} + +static void vu_draw_select(t_vu* x,t_glist* glist) +{ + int i; + t_canvas *canvas = glist_getcanvas(glist); + + if(x->x_gui.x_fsf.x_selected) + { + sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + for(i = 1; i <= IEM_VU_STEPS; i++) + { + if(((i+2) & 3) && (x->x_scale)) + sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -fill #%06x\n", + canvas, x, i, IEM_GUI_COLOR_SELECTED); + } + if(x->x_scale) + { + i = IEM_VU_STEPS + 1; + sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -fill #%06x\n", + canvas, x, i, IEM_GUI_COLOR_SELECTED); + } + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + } + else + { + sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_NORMAL); + for(i = 1; i <= IEM_VU_STEPS; i++) + { + if(((i+2) & 3) && (x->x_scale)) + sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -fill #%06x\n", + canvas, x, i, x->x_gui.x_lcol); + } + if(x->x_scale) + { + i = IEM_VU_STEPS+1; + sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -fill #%06x\n", + canvas, x, i, x->x_gui.x_lcol); + } + sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, x->x_gui.x_lcol); + } +} + +void vu_draw(t_vu *x, t_glist *glist, int mode) +{ + if(mode == IEM_GUI_DRAW_MODE_MOVE) + vu_draw_move(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_NEW) + vu_draw_new(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_SELECT) + vu_draw_select(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_ERASE) + vu_draw_erase(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_CONFIG) + vu_draw_config(x, glist); + else if(mode >= IEM_GUI_DRAW_MODE_IO) + vu_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO); +} + +/* ------------------------ vu widgetbehaviour----------------------------- */ + +static void vu_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_vu* x = (t_vu*)z; + int hmargin = HMARGIN * IEMGUI_ZOOM(x), vmargin = VMARGIN * IEMGUI_ZOOM(x); + + *xp1 = text_xpix(&x->x_gui.x_obj, glist) - hmargin; + *yp1 = text_ypix(&x->x_gui.x_obj, glist) - vmargin; + *xp2 = *xp1 + x->x_gui.x_w + hmargin*2; + *yp2 = *yp1 + x->x_gui.x_h + vmargin*2; +} + +static void vu_save(t_gobj *z, t_binbuf *b) +{ + t_vu *x = (t_vu *)z; + t_symbol *bflcol[3]; + t_symbol *srl[3]; + + iemgui_save(&x->x_gui, srl, bflcol); + binbuf_addv(b, "ssiisiissiiiissii", gensym("#X"), gensym("obj"), + (int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix, + gensym("vu"), x->x_gui.x_w/IEMGUI_ZOOM(x), x->x_gui.x_h/IEMGUI_ZOOM(x), + srl[1], srl[2], + x->x_gui.x_ldx, x->x_gui.x_ldy, + iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize, + bflcol[0], bflcol[2], x->x_scale, + iem_symargstoint(&x->x_gui.x_isa)); + binbuf_addv(b, ";"); +} + +void vu_check_height(t_vu *x, int h) +{ + int n; + + n = h / IEM_VU_STEPS; + if(n < IEM_VU_MINSIZE) + n = IEM_VU_MINSIZE; + x->x_led_size = n - 1; + x->x_gui.x_h = (IEM_VU_STEPS * n) * IEMGUI_ZOOM(x); +} + +static void vu_scale(t_vu *x, t_floatarg fscale) +{ + int i, scale = (int)fscale; + + if(scale != 0) scale = 1; + if(x->x_scale && !scale) + { + t_canvas *canvas = glist_getcanvas(x->x_gui.x_glist); + + x->x_scale = (int)scale; + if(glist_isvisible(x->x_gui.x_glist)) + { + for(i = 1; i <= IEM_VU_STEPS; i++) + { + if((i+2) & 3) + sys_vgui(".x%lx.c delete %lxSCALE%d\n", canvas, x, i); + } + i = IEM_VU_STEPS + 1; + sys_vgui(".x%lx.c delete %lxSCALE%d\n", canvas, x, i); + } + } + if(!x->x_scale && scale) + { + int w4 = x->x_gui.x_w/4; + int end = text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist) + x->x_gui.x_w + 4*IEMGUI_ZOOM(x); + int k1 = (x->x_led_size+1)*IEMGUI_ZOOM(x), k2 = IEM_VU_STEPS+1, k3 = k1/2; + int yyy, k4 = text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist) - k3; + int fs = x->x_gui.x_fontsize * IEMGUI_ZOOM(x); + t_canvas *canvas = glist_getcanvas(x->x_gui.x_glist); + + x->x_scale = (int)scale; + if(glist_isvisible(x->x_gui.x_glist)) + { + for(i = 1; i <= IEM_VU_STEPS; i++) + { + yyy = k4 + k1 * (k2 - i); + if((i+2) & 3) + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \ + -font {{%s} -%d %s} -fill #%06x -tags %lxSCALE%d\n", + canvas, end, yyy + k3, iemgui_vu_scale_str[i], + x->x_gui.x_font, fs, + sys_fontweight, x->x_gui.x_lcol, x, i); + } + i = IEM_VU_STEPS + 1; + yyy = k4 + k1 * (k2 - i); + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \ + -font {{%s} -%d %s} -fill #%06x -tags %lxSCALE%d\n", + canvas, end, yyy + k3, iemgui_vu_scale_str[i], + x->x_gui.x_font, fs, + sys_fontweight, x->x_gui.x_lcol, x, i); + } + } +} + +static void vu_properties(t_gobj *z, t_glist *owner) +{ + t_vu *x = (t_vu *)z; + char buf[800]; + t_symbol *srl[3]; + + iemgui_properties(&x->x_gui, srl); + sprintf(buf, "pdtk_iemgui_dialog %%s |vu| \ + --------dimensions(pix)(pix):-------- %d %d width: %d %d height: \ + empty 0.0 empty 0.0 empty %d \ + %d no_scale scale %d %d empty %d \ + %s %s \ + %s %d %d \ + %d %d \ + #%06x none #%06x\n", + x->x_gui.x_w/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE, + x->x_gui.x_h/IEMGUI_ZOOM(x), IEM_VU_STEPS*IEM_VU_MINSIZE, + 0,/*no_schedule*/ + x->x_scale, -1, -1, -1,/*no linlog, no init, no multi*/ + "nosndno", srl[1]->s_name,/*no send*/ + srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy, + x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize, + 0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_lcol); + gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf); +} + +static void vu_dialog(t_vu *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *srl[3]; + int w = (int)atom_getfloatarg(0, argc, argv); + int h = (int)atom_getfloatarg(1, argc, argv); + int scale = (int)atom_getfloatarg(4, argc, argv); + int sr_flags; + + srl[0] = gensym("empty"); + sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv); + x->x_gui.x_fsf.x_snd_able = 0; + x->x_gui.x_isa.x_loadinit = 0; + x->x_gui.x_w = iemgui_clip_size(w) * IEMGUI_ZOOM(x); + vu_check_height(x, h); + if(scale != 0) + scale = 1; + vu_scale(x, (t_float)scale); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x); +} + +static void vu_size(t_vu *x, t_symbol *s, int ac, t_atom *av) +{ + x->x_gui.x_w = iemgui_clip_size((int)atom_getfloatarg(0, ac, av)) * IEMGUI_ZOOM(x); + if(ac > 1) + vu_check_height(x, (int)atom_getfloatarg(1, ac, av)); + if(glist_isvisible(x->x_gui.x_glist)) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG); + canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x); + } +} + +static void vu_delta(t_vu *x, t_symbol *s, int ac, t_atom *av) +{iemgui_delta((void *)x, &x->x_gui, s, ac, av);} + +static void vu_pos(t_vu *x, t_symbol *s, int ac, t_atom *av) +{iemgui_pos((void *)x, &x->x_gui, s, ac, av);} + +static void vu_color(t_vu *x, t_symbol *s, int ac, t_atom *av) +{iemgui_color((void *)x, &x->x_gui, s, ac, av);} + +static void vu_receive(t_vu *x, t_symbol *s) +{iemgui_receive(x, &x->x_gui, s);} + +static void vu_label(t_vu *x, t_symbol *s) +{iemgui_label((void *)x, &x->x_gui, s);} + +static void vu_label_pos(t_vu *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);} + +static void vu_label_font(t_vu *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);} + +static void vu_float(t_vu *x, t_floatarg rms) +{ + int i; + int old = x->x_rms; + if(rms <= IEM_VU_MINDB) + x->x_rms = 0; + else if(rms >= IEM_VU_MAXDB) + x->x_rms = IEM_VU_STEPS; + else + { + int i = (int)(2.0*(rms + IEM_VU_OFFSET)); + x->x_rms = iemgui_vu_db2i[i]; + } + i = (int)(100.0*rms + 10000.5); + rms = 0.01*(t_float)(i - 10000); + x->x_fr = rms; + outlet_float(x->x_out_rms, rms); + x->x_updaterms = 1; + if(x->x_rms != old) + sys_queuegui(x, x->x_gui.x_glist, vu_draw_update); +} + +static void vu_ft1(t_vu *x, t_floatarg peak) +{ + int i; + int old = x->x_peak; + if(peak <= IEM_VU_MINDB) + x->x_peak = 0; + else if(peak >= IEM_VU_MAXDB) + x->x_peak = IEM_VU_STEPS; + else + { + int i = (int)(2.0*(peak + IEM_VU_OFFSET)); + x->x_peak = iemgui_vu_db2i[i]; + } + i = (int)(100.0*peak + 10000.5); + peak = 0.01*(t_float)(i - 10000); + x->x_fp = peak; + x->x_updatepeak = 1; + if(x->x_peak != old) + sys_queuegui(x, x->x_gui.x_glist, vu_draw_update); + outlet_float(x->x_out_peak, peak); +} + +static void vu_bang(t_vu *x) +{ + outlet_float(x->x_out_peak, x->x_fp); + outlet_float(x->x_out_rms, x->x_fr); + x->x_updaterms = x->x_updatepeak = 1; + sys_queuegui(x, x->x_gui.x_glist, vu_draw_update); +} + +static void *vu_new(t_symbol *s, int argc, t_atom *argv) +{ + t_vu *x = (t_vu *)pd_new(vu_class); + int w = IEM_GUI_DEFAULTSIZE, h = IEM_VU_STEPS*IEM_VU_DEFAULTSIZE; + int ldx = -1, ldy = -8, f = 0, fs = 10, scale =1; + int ftbreak = IEM_BNG_DEFAULTBREAKFLASHTIME, fthold = IEM_BNG_DEFAULTHOLDFLASHTIME; + char str[144]; + + iem_inttosymargs(&x->x_gui.x_isa, 0); + iem_inttofstyle(&x->x_gui.x_fsf, 0); + + x->x_gui.x_bcol = 0x404040; + x->x_gui.x_fcol = 0x00; + x->x_gui.x_lcol = 0x00; + + if((argc >= 11)&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1) + &&(IS_A_SYMBOL(argv,2)||IS_A_FLOAT(argv,2)) + &&(IS_A_SYMBOL(argv,3)||IS_A_FLOAT(argv,3)) + &&IS_A_FLOAT(argv,4)&&IS_A_FLOAT(argv,5) + &&IS_A_FLOAT(argv,6)&&IS_A_FLOAT(argv,7) + &&IS_A_FLOAT(argv,10)) + { + w = (int)atom_getfloatarg(0, argc, argv); + h = (int)atom_getfloatarg(1, argc, argv); + iemgui_new_getnames(&x->x_gui, 1, argv); + ldx = (int)atom_getfloatarg(4, argc, argv); + ldy = (int)atom_getfloatarg(5, argc, argv); + iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(6, argc, argv)); + fs = (int)atom_getfloatarg(7, argc, argv); + iemgui_all_loadcolors(&x->x_gui, argv+8, NULL, argv+9); + scale = (int)atom_getfloatarg(10, argc, argv); + } + else iemgui_new_getnames(&x->x_gui, 1, 0); + if((argc == 12)&&IS_A_FLOAT(argv,11)) + iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(11, argc, argv)); + x->x_gui.x_draw = (t_iemfunptr)vu_draw; + + x->x_gui.x_fsf.x_snd_able = 0; + x->x_gui.x_fsf.x_rcv_able = 1; + x->x_gui.x_glist = (t_glist *)canvas_getcurrent(); + if (!strcmp(x->x_gui.x_rcv->s_name, "empty")) + x->x_gui.x_fsf.x_rcv_able = 0; + if (x->x_gui.x_fsf.x_font_style == 1) + strcpy(x->x_gui.x_font, "helvetica"); + else if(x->x_gui.x_fsf.x_font_style == 2) + strcpy(x->x_gui.x_font, "times"); + else { x->x_gui.x_fsf.x_font_style = 0; + strcpy(x->x_gui.x_font, sys_font); } + if(x->x_gui.x_fsf.x_rcv_able) + pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + x->x_gui.x_ldx = ldx; + x->x_gui.x_ldy = ldy; + if(fs < 4) + fs = 4; + x->x_gui.x_fontsize = fs; + x->x_gui.x_w = iemgui_clip_size(w); + vu_check_height(x, h); + if(scale != 0) + scale = 1; + x->x_scale = scale; + x->x_peak = 0; + x->x_rms = 0; + x->x_fp = -101.0; + x->x_fr = -101.0; + iemgui_verify_snd_ne_rcv(&x->x_gui); + inlet_new(&x->x_gui.x_obj, &x->x_gui.x_obj.ob_pd, &s_float, gensym("ft1")); + x->x_out_rms = outlet_new(&x->x_gui.x_obj, &s_float); + x->x_out_peak = outlet_new(&x->x_gui.x_obj, &s_float); + iemgui_newzoom(&x->x_gui); + return (x); +} + +static void vu_free(t_vu *x) +{ + if(x->x_gui.x_fsf.x_rcv_able) + pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + gfxstub_deleteforkey(x); +} + +void g_vumeter_setup(void) +{ + vu_class = class_new(gensym("vu"), (t_newmethod)vu_new, + (t_method)vu_free, sizeof(t_vu), 0, A_GIMME, 0); + class_addbang(vu_class,vu_bang); + class_addfloat(vu_class,vu_float); + class_addmethod(vu_class, (t_method)vu_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(vu_class, (t_method)vu_dialog, + gensym("dialog"), A_GIMME, 0); + class_addmethod(vu_class, (t_method)vu_size, + gensym("size"), A_GIMME, 0); + class_addmethod(vu_class, (t_method)vu_scale, + gensym("scale"), A_DEFFLOAT, 0); + class_addmethod(vu_class, (t_method)vu_delta, + gensym("delta"), A_GIMME, 0); + class_addmethod(vu_class, (t_method)vu_pos, + gensym("pos"), A_GIMME, 0); + class_addmethod(vu_class, (t_method)vu_color, + gensym("color"), A_GIMME, 0); + class_addmethod(vu_class, (t_method)vu_receive, + gensym("receive"), A_DEFSYM, 0); + class_addmethod(vu_class, (t_method)vu_label, + gensym("label"), A_DEFSYM, 0); + class_addmethod(vu_class, (t_method)vu_label_pos, + gensym("label_pos"), A_GIMME, 0); + class_addmethod(vu_class, (t_method)vu_label_font, + gensym("label_font"), A_GIMME, 0); + class_addmethod(vu_class, (t_method)iemgui_zoom, + gensym("zoom"), A_CANT, 0); + vu_widgetbehavior.w_getrectfn = vu_getrect; + vu_widgetbehavior.w_displacefn = iemgui_displace; + vu_widgetbehavior.w_selectfn = iemgui_select; + vu_widgetbehavior.w_activatefn = NULL; + vu_widgetbehavior.w_deletefn = iemgui_delete; + vu_widgetbehavior.w_visfn = iemgui_vis; + vu_widgetbehavior.w_clickfn = NULL; + class_setwidget(vu_class,&vu_widgetbehavior); + class_sethelpsymbol(vu_class, gensym("vu")); + class_setsavefn(vu_class, vu_save); + class_setpropertiesfn(vu_class, vu_properties); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/m_atom.c b/ports/camomile/source/LibPd/pure-data/src/m_atom.c new file mode 100644 index 00000000..02a8e747 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/m_atom.c @@ -0,0 +1,128 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include +#include + + /* convenience routines for checking and getting values of + atoms. There's no "pointer" version since there's nothing + safe to return if there's an error. */ + +t_float atom_getfloat(t_atom *a) +{ + if (a->a_type == A_FLOAT) return (a->a_w.w_float); + else return (0); +} + +t_int atom_getint(t_atom *a) +{ + return (atom_getfloat(a)); +} + +t_symbol *atom_getsymbol(t_atom *a) /* LATER think about this more carefully */ +{ + if (a->a_type == A_SYMBOL) return (a->a_w.w_symbol); + else return (&s_float); +} + +t_symbol *atom_gensym(t_atom *a) /* this works better for graph labels */ +{ + char buf[30]; + if (a->a_type == A_SYMBOL) return (a->a_w.w_symbol); + else if (a->a_type == A_FLOAT) + sprintf(buf, "%g", a->a_w.w_float); + else strcpy(buf, "???"); + return (gensym(buf)); +} + +t_float atom_getfloatarg(int which, int argc, t_atom *argv) +{ + if (argc <= which) return (0); + argv += which; + if (argv->a_type == A_FLOAT) return (argv->a_w.w_float); + else return (0); +} + +t_int atom_getintarg(int which, int argc, t_atom *argv) +{ + return (atom_getfloatarg(which, argc, argv)); +} + +t_symbol *atom_getsymbolarg(int which, int argc, t_atom *argv) +{ + if (argc <= which) return (&s_); + argv += which; + if (argv->a_type == A_SYMBOL) return (argv->a_w.w_symbol); + else return (&s_); +} + +/* convert an atom into a string, in the reverse sense of binbuf_text (q.v.) +* special attention is paid to symbols containing the special characters +* ';', ',', '$', and '\'; these are quoted with a preceding '\', except that +* the '$' only gets quoted at the beginning of the string. +*/ + +void atom_string(t_atom *a, char *buf, unsigned int bufsize) +{ + char tbuf[30]; + switch(a->a_type) + { + case A_SEMI: strcpy(buf, ";"); break; + case A_COMMA: strcpy(buf, ","); break; + case A_POINTER: + strcpy(buf, "(pointer)"); + break; + case A_FLOAT: + sprintf(tbuf, "%g", a->a_w.w_float); + if (strlen(tbuf) < bufsize-1) strcpy(buf, tbuf); + else if (a->a_w.w_float < 0) strcpy(buf, "-"); + else strcpy(buf, "+"); + break; + case A_SYMBOL: + { + char *sp; + unsigned int len; + int quote; + for (sp = a->a_w.w_symbol->s_name, len = 0, quote = 0; *sp; sp++, len++) + if (*sp == ';' || *sp == ',' || *sp == '\\' || + (*sp == '$' && sp[1] >= '0' && sp[1] <= '9')) + quote = 1; + if (quote) + { + char *bp = buf, *ep = buf + (bufsize-2); + sp = a->a_w.w_symbol->s_name; + while (bp < ep && *sp) + { + if (*sp == ';' || *sp == ',' || *sp == '\\' || + (*sp == '$' && sp[1] >= '0' && sp[1] <= '9')) + *bp++ = '\\'; + *bp++ = *sp++; + } + if (*sp) *bp++ = '*'; + *bp = 0; + /* post("quote %s -> %s", a->a_w.w_symbol->s_name, buf); */ + } + else + { + if (len < bufsize-1) strcpy(buf, a->a_w.w_symbol->s_name); + else + { + strncpy(buf, a->a_w.w_symbol->s_name, bufsize - 2); + strcpy(buf + (bufsize - 2), "*"); + } + } + } + break; + case A_DOLLAR: + sprintf(buf, "$%d", a->a_w.w_index); + break; + case A_DOLLSYM: + strncpy(buf, a->a_w.w_symbol->s_name, bufsize); + buf[bufsize-1] = 0; + break; + default: + bug("atom_string"); + } +} diff --git a/ports/camomile/source/LibPd/pure-data/src/m_binbuf.c b/ports/camomile/source/LibPd/pure-data/src/m_binbuf.c new file mode 100644 index 00000000..ad7f6e25 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/m_binbuf.c @@ -0,0 +1,1546 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + + +#include +#include "m_pd.h" +#include "s_stuff.h" +#include "g_canvas.h" +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef _WIN32 +#include +#endif +#include +#include +#include + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +struct _binbuf +{ + int b_n; + t_atom *b_vec; +}; + +t_binbuf *binbuf_new(void) +{ + t_binbuf *x = (t_binbuf *)t_getbytes(sizeof(*x)); + x->b_n = 0; + x->b_vec = t_getbytes(0); + return (x); +} + +void binbuf_free(t_binbuf *x) +{ + t_freebytes(x->b_vec, x->b_n * sizeof(*x->b_vec)); + t_freebytes(x, sizeof(*x)); +} + +t_binbuf *binbuf_duplicate(t_binbuf *y) +{ + t_binbuf *x = (t_binbuf *)t_getbytes(sizeof(*x)); + x->b_n = y->b_n; + x->b_vec = t_getbytes(x->b_n * sizeof(*x->b_vec)); + memcpy(x->b_vec, y->b_vec, x->b_n * sizeof(*x->b_vec)); + return (x); +} + +void binbuf_clear(t_binbuf *x) +{ + x->b_vec = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec), 0); + x->b_n = 0; +} + + /* convert text to a binbuf */ +void binbuf_text(t_binbuf *x, const char *text, size_t size) +{ + char buf[MAXPDSTRING+1], *bufp, *ebuf = buf+MAXPDSTRING; + const char *textp = text, *etext = text+size; + t_atom *ap; + int nalloc = 16, natom = 0; + t_freebytes(x->b_vec, x->b_n * sizeof(*x->b_vec)); + x->b_vec = t_getbytes(nalloc * sizeof(*x->b_vec)); + ap = x->b_vec; + x->b_n = 0; + while (1) + { + int type; + /* skip leading space */ + while ((textp != etext) && (*textp == ' ' || *textp == '\n' + || *textp == '\r' || *textp == '\t')) textp++; + if (textp == etext) break; + if (*textp == ';') SETSEMI(ap), textp++; + else if (*textp == ',') SETCOMMA(ap), textp++; + else + { + /* it's an atom other than a comma or semi */ + char c; + int floatstate = 0, slash = 0, lastslash = 0, dollar = 0; + bufp = buf; + do + { + c = *bufp = *textp++; + lastslash = slash; + slash = (c == '\\'); + + if (floatstate >= 0) + { + int digit = (c >= '0' && c <= '9'), + dot = (c == '.'), minus = (c == '-'), + plusminus = (minus || (c == '+')), + expon = (c == 'e' || c == 'E'); + if (floatstate == 0) /* beginning */ + { + if (minus) floatstate = 1; + else if (digit) floatstate = 2; + else if (dot) floatstate = 3; + else floatstate = -1; + } + else if (floatstate == 1) /* got minus */ + { + if (digit) floatstate = 2; + else if (dot) floatstate = 3; + else floatstate = -1; + } + else if (floatstate == 2) /* got digits */ + { + if (dot) floatstate = 4; + else if (expon) floatstate = 6; + else if (!digit) floatstate = -1; + } + else if (floatstate == 3) /* got '.' without digits */ + { + if (digit) floatstate = 5; + else floatstate = -1; + } + else if (floatstate == 4) /* got '.' after digits */ + { + if (digit) floatstate = 5; + else if (expon) floatstate = 6; + else floatstate = -1; + } + else if (floatstate == 5) /* got digits after . */ + { + if (expon) floatstate = 6; + else if (!digit) floatstate = -1; + } + else if (floatstate == 6) /* got 'e' */ + { + if (plusminus) floatstate = 7; + else if (digit) floatstate = 8; + else floatstate = -1; + } + else if (floatstate == 7) /* got plus or minus */ + { + if (digit) floatstate = 8; + else floatstate = -1; + } + else if (floatstate == 8) /* got digits */ + { + if (!digit) floatstate = -1; + } + } + if (!lastslash && c == '$' && (textp != etext && + textp[0] >= '0' && textp[0] <= '9')) + dollar = 1; + if (!slash) bufp++; + else if (lastslash) + { + bufp++; + slash = 0; + } + } + while (textp != etext && bufp != ebuf && + (slash || (*textp != ' ' && *textp != '\n' && *textp != '\r' + && *textp != '\t' &&*textp != ',' && *textp != ';'))); + *bufp = 0; +#if 0 + post("binbuf_text: buf %s", buf); +#endif + if (floatstate == 2 || floatstate == 4 || floatstate == 5 || + floatstate == 8) + SETFLOAT(ap, atof(buf)); + /* LATER try to figure out how to mix "$" and "\$" correctly; + here, the backslashes were already stripped so we assume all + "$" chars are real dollars. In fact, we only know at least one + was. */ + else if (dollar) + { + if (buf[0] != '$') + dollar = 0; + for (bufp = buf+1; *bufp; bufp++) + if (*bufp < '0' || *bufp > '9') + dollar = 0; + if (dollar) + SETDOLLAR(ap, atoi(buf+1)); + else SETDOLLSYM(ap, gensym(buf)); + } + else SETSYMBOL(ap, gensym(buf)); + } + ap++; + natom++; + if (natom == nalloc) + { + x->b_vec = t_resizebytes(x->b_vec, nalloc * sizeof(*x->b_vec), + nalloc * (2*sizeof(*x->b_vec))); + nalloc = nalloc * 2; + ap = x->b_vec + natom; + } + if (textp == etext) break; + } + /* reallocate the vector to exactly the right size */ + x->b_vec = t_resizebytes(x->b_vec, nalloc * sizeof(*x->b_vec), + natom * sizeof(*x->b_vec)); + x->b_n = natom; +} + + /* convert a binbuf to text; no null termination. */ +void binbuf_gettext(t_binbuf *x, char **bufp, int *lengthp) +{ + char *buf = getbytes(0), *newbuf; + int length = 0; + char string[MAXPDSTRING]; + t_atom *ap; + int indx; + + for (ap = x->b_vec, indx = x->b_n; indx--; ap++) + { + int newlength; + if ((ap->a_type == A_SEMI || ap->a_type == A_COMMA) && + length && buf[length-1] == ' ') length--; + atom_string(ap, string, MAXPDSTRING); + newlength = length + (int)strlen(string) + 1; + if (!(newbuf = resizebytes(buf, length, newlength))) break; + buf = newbuf; + strcpy(buf + length, string); + length = newlength; + if (ap->a_type == A_SEMI) buf[length-1] = '\n'; + else buf[length-1] = ' '; + } + if (length && buf[length-1] == ' ') + { + if ((newbuf = t_resizebytes(buf, length, length-1))) + { + buf = newbuf; + length--; + } + } + *bufp = buf; + *lengthp = length; +} + +/* LATER improve the out-of-space behavior below. Also fix this so that +writing to file doesn't buffer everything together. */ + +void binbuf_add(t_binbuf *x, int argc, t_atom *argv) +{ + int newsize = x->b_n + argc, i; + t_atom *ap; + if ((ap = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec), + newsize * sizeof(*x->b_vec)))) + x->b_vec = ap; + else + { + error("binbuf_addmessage: out of space"); + return; + } +#if 0 + startpost("binbuf_add: "); + postatom(argc, argv); + endpost(); +#endif + for (ap = x->b_vec + x->b_n, i = argc; i--; ap++) + *ap = *(argv++); + x->b_n = newsize; +} + +#define MAXADDMESSV 100 +void binbuf_addv(t_binbuf *x, char *fmt, ...) +{ + va_list ap; + t_atom arg[MAXADDMESSV], *at =arg; + int nargs = 0; + char *fp = fmt; + + va_start(ap, fmt); + while (1) + { + if (nargs >= MAXADDMESSV) + { + error("binbuf_addmessv: only %d allowed", MAXADDMESSV); + break; + } + switch(*fp++) + { + case 'i': SETFLOAT(at, va_arg(ap, int)); break; + case 'f': SETFLOAT(at, va_arg(ap, double)); break; + case 's': SETSYMBOL(at, va_arg(ap, t_symbol *)); break; + case ';': SETSEMI(at); break; + case ',': SETCOMMA(at); break; + default: goto done; + } + at++; + nargs++; + } +done: + va_end(ap); + binbuf_add(x, nargs, arg); +} + +/* add a binbuf to another one for saving. Semicolons and commas go to +symbols ";", "'",; and inside symbols, characters ';', ',' and '$' get +escaped. LATER also figure out about escaping white space */ + +void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y) +{ + t_binbuf *z = binbuf_new(); + int i, fixit; + t_atom *ap; + binbuf_add(z, y->b_n, y->b_vec); + for (i = 0, ap = z->b_vec; i < z->b_n; i++, ap++) + { + char tbuf[MAXPDSTRING], *s; + switch (ap->a_type) + { + case A_FLOAT: + break; + case A_SEMI: + SETSYMBOL(ap, gensym(";")); + break; + case A_COMMA: + SETSYMBOL(ap, gensym(",")); + break; + case A_DOLLAR: + sprintf(tbuf, "$%d", ap->a_w.w_index); + SETSYMBOL(ap, gensym(tbuf)); + break; + case A_DOLLSYM: + atom_string(ap, tbuf, MAXPDSTRING); + SETSYMBOL(ap, gensym(tbuf)); + break; + case A_SYMBOL: + for (s = ap->a_w.w_symbol->s_name, fixit = 0; *s; s++) + if (*s == ';' || *s == ',' || *s == '$') + fixit = 1; + if (fixit) + { + atom_string(ap, tbuf, MAXPDSTRING); + SETSYMBOL(ap, gensym(tbuf)); + } + break; + default: + bug("binbuf_addbinbuf"); + } + } + + binbuf_add(x, z->b_n, z->b_vec); + binbuf_free(z); +} + +void binbuf_addsemi(t_binbuf *x) +{ + t_atom a; + SETSEMI(&a); + binbuf_add(x, 1, &a); +} + +/* Supply atoms to a binbuf from a message, making the opposite changes +from binbuf_addbinbuf. The symbol ";" goes to a semicolon, etc. */ + +void binbuf_restore(t_binbuf *x, int argc, t_atom *argv) +{ + int newsize = x->b_n + argc, i; + t_atom *ap; + if ((ap = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec), + newsize * sizeof(*x->b_vec)))) + x->b_vec = ap; + else + { + error("binbuf_addmessage: out of space"); + return; + } + + for (ap = x->b_vec + x->b_n, i = argc; i--; ap++) + { + if (argv->a_type == A_SYMBOL) + { + char *str = argv->a_w.w_symbol->s_name, *str2; + if (!strcmp(str, ";")) SETSEMI(ap); + else if (!strcmp(str, ",")) SETCOMMA(ap); + else if ((str2 = strchr(str, '$')) && str2[1] >= '0' + && str2[1] <= '9') + { + int dollsym = 0; + if (*str != '$') + dollsym = 1; + else for (str2 = str + 1; *str2; str2++) + if (*str2 < '0' || *str2 > '9') + { + dollsym = 1; + break; + } + if (dollsym) + SETDOLLSYM(ap, gensym(str)); + else + { + int dollar = 0; + sscanf(argv->a_w.w_symbol->s_name + 1, "%d", &dollar); + SETDOLLAR(ap, dollar); + } + } + else if (strchr(argv->a_w.w_symbol->s_name, '\\')) + { + char buf[MAXPDSTRING], *sp1, *sp2; + int slashed = 0; + for (sp1 = buf, sp2 = argv->a_w.w_symbol->s_name; + *sp2 && sp1 < buf + (MAXPDSTRING-1); + sp2++) + { + if (slashed) + *sp1++ = *sp2; + else if (*sp2 == '\\') + slashed = 1; + else *sp1++ = *sp2, slashed = 0; + } + *sp1 = 0; + SETSYMBOL(ap, gensym(buf)); + } + else *ap = *argv; + argv++; + } + else *ap = *(argv++); + } + x->b_n = newsize; +} + +void binbuf_print(t_binbuf *x) +{ + int i, startedpost = 0, newline = 1; + for (i = 0; i < x->b_n; i++) + { + if (newline) + { + if (startedpost) endpost(); + startpost(""); + startedpost = 1; + } + postatom(1, x->b_vec + i); + if (x->b_vec[i].a_type == A_SEMI) + newline = 1; + else newline = 0; + } + if (startedpost) endpost(); +} + +int binbuf_getnatom(t_binbuf *x) +{ + return (x->b_n); +} + +t_atom *binbuf_getvec(t_binbuf *x) +{ + return (x->b_vec); +} + +int binbuf_resize(t_binbuf *x, int newsize) +{ + t_atom *new = t_resizebytes(x->b_vec, + x->b_n * sizeof(*x->b_vec), newsize * sizeof(*x->b_vec)); + if (new) + x->b_vec = new, x->b_n = newsize; + return (new != 0); +} + +int canvas_getdollarzero( void); + +/* JMZ: + * s points to the first character after the $ + * (e.g. if the org.symbol is "$1-bla", then s will point to "1-bla") + * (e.g. org.symbol="hu-$1mu", s="1mu") + * LATER: think about more complex $args, like ${$1+3} + * + * the return value holds the length of the $arg (in most cases: 1) + * buf holds the expanded $arg + * + * if some error occurred, "-1" is returned + * + * e.g. "$1-bla" with list "10 20 30" + * s="1-bla" + * buf="10" + * return value = 1; (s+1=="-bla") + */ +int binbuf_expanddollsym(char*s, char*buf,t_atom dollar0, int ac, t_atom *av, int tonew) +{ + int argno = (int)atol(s); + int arglen=0; + char*cs=s; + char c=*cs; + *buf=0; + + while(c&&(c>='0')&&(c<='9')){ + c=*cs++; + arglen++; + } + + if (cs==s) { /* invalid $-expansion (like "$bla") */ + sprintf(buf, "$"); + return 0; + } + else if (argno < 0 || argno > ac) /* undefined argument */ + { + if(!tonew)return 0; + sprintf(buf, "$%d", argno); + } + else if (argno == 0){ /* $0 */ + atom_string(&dollar0, buf, MAXPDSTRING/2-1); + } + else{ /* fine! */ + atom_string(av+(argno-1), buf, MAXPDSTRING/2-1); + } + return (arglen-1); +} + +/* LATER remove the dependence on the current canvas for $0; should be another +argument. */ +t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew) +{ + char buf[MAXPDSTRING]; + char buf2[MAXPDSTRING]; + char*str=s->s_name; + char*substr; + int next=0, i=MAXPDSTRING; + t_atom dollarnull; + SETFLOAT(&dollarnull, canvas_getdollarzero()); + while(i--)buf2[i]=0; + +#if 1 + /* JMZ: currently, a symbol is detected to be A_DOLLSYM if it starts with '$' + * the leading $ is stripped and the rest stored in "s" + * i would suggest to NOT strip the leading $ + * and make everything a A_DOLLSYM that contains(!) a $ + * + * whenever this happened, enable this code + */ + substr=strchr(str, '$'); + if (!substr || substr-str >= MAXPDSTRING) + return (s); + + strncat(buf2, str, (substr-str)); + str=substr+1; + +#endif + + while((next=binbuf_expanddollsym(str, buf, dollarnull, ac, av, tonew))>=0) + { + /* + * JMZ: i am not sure what this means, so i might have broken it + * it seems like that if "tonew" is set and the $arg cannot be expanded + * (or the dollarsym is in reality a A_DOLLAR) + * 0 is returned from binbuf_realizedollsym + * this happens, when expanding in a message-box, but does not happen + * when the A_DOLLSYM is the name of a subpatch + */ + if(!tonew&&(0==next)&&(0==*buf)) + { + return 0; /* JMZ: this should mimic the original behaviour */ + } + + strncat(buf2, buf, MAXPDSTRING/2-1); + str+=next; + substr=strchr(str, '$'); + if(substr) + { + strncat(buf2, str, (substr-str)); + str=substr+1; + } + else + { + strncat(buf2, str, MAXPDSTRING-1); + goto done; + } + } +done: + return (gensym(buf2)); +} + +#define SMALLMSG 5 +#define HUGEMSG 1000 + +#ifndef HAVE_ALLOCA /* can work without alloca() but we never need it */ +#define HAVE_ALLOCA 1 +#endif + +#ifdef HAVE_ALLOCA + +#ifdef _WIN32 +# include /* MSVC or mingw on windows */ +#elif defined(__linux__) || defined(__APPLE__) +# include /* linux, mac, mingw, cygwin */ +#else +# include /* BSDs for example */ +#endif + +#define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)((n) < HUGEMSG ? \ + alloca((n) * sizeof(t_atom)) : getbytes((n) * sizeof(t_atom)))) +#define ATOMS_FREEA(x, n) ( \ + ((n) < HUGEMSG || (freebytes((x), (n) * sizeof(t_atom)), 0))) +#else +#define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)getbytes((n) * sizeof(t_atom))) +#define ATOMS_FREEA(x, n) (freebytes((x), (n) * sizeof(t_atom))) +#endif + +void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv) +{ + t_atom smallstack[SMALLMSG], *mstack, *msp; + t_atom *at = x->b_vec; + int ac = x->b_n; + int nargs, maxnargs = 0; + if (ac <= SMALLMSG) + mstack = smallstack; + else + { +#if 1 + /* count number of args in biggest message. The weird + treatment of "pd_objectmaker" is because when the message + goes out to objectmaker, commas and semis are passed + on as regular args (see below). We're tacitly assuming here + that the pd_objectmaker target can't come up via a named + destination in the message, only because the original "target" + points there. */ + if (target == &pd_objectmaker) + maxnargs = ac; + else + { + int i, j = (target ? 0 : -1); + for (i = 0; i < ac; i++) + { + if (at[i].a_type == A_SEMI) + j = -1; + else if (at[i].a_type == A_COMMA) + j = 0; + else if (++j > maxnargs) + maxnargs = j; + } + } + if (maxnargs <= SMALLMSG) + mstack = smallstack; + else ATOMS_ALLOCA(mstack, maxnargs); +#else + /* just pessimistically allocate enough to hold everything + at once. This turned out to run slower in a simple benchmark + I tried, perhaps because the extra memory allocation + hurt the cache hit rate. */ + maxnargs = ac; + ATOMS_ALLOCA(mstack, maxnargs); +#endif + + } + msp = mstack; + while (1) + { + t_pd *nexttarget; + /* get a target. */ + while (!target) + { + t_symbol *s; + while (ac && (at->a_type == A_SEMI || at->a_type == A_COMMA)) + ac--, at++; + if (!ac) break; + if (at->a_type == A_DOLLAR) + { + if (at->a_w.w_index <= 0 || at->a_w.w_index > argc) + { + error("$%d: not enough arguments supplied", + at->a_w.w_index); + goto cleanup; + } + else if (argv[at->a_w.w_index-1].a_type != A_SYMBOL) + { + error("$%d: symbol needed as message destination", + at->a_w.w_index); + goto cleanup; + } + else s = argv[at->a_w.w_index-1].a_w.w_symbol; + } + else if (at->a_type == A_DOLLSYM) + { + if (!(s = binbuf_realizedollsym(at->a_w.w_symbol, + argc, argv, 0))) + { + error("$%s: not enough arguments supplied", + at->a_w.w_symbol->s_name); + goto cleanup; + } + } + else s = atom_getsymbol(at); + if (!(target = s->s_thing)) + { + error("%s: no such object", s->s_name); + cleanup: + do at++, ac--; + while (ac && at->a_type != A_SEMI); + /* LATER eat args until semicolon and continue */ + continue; + } + else + { + at++, ac--; + break; + } + } + if (!ac) break; + nargs = 0; + nexttarget = target; + while (1) + { + t_symbol *s9; + if (!ac) goto gotmess; + switch (at->a_type) + { + case A_SEMI: + /* semis and commas in new message just get bashed to + a symbol. This is needed so you can pass them to "expr." */ + if (target == &pd_objectmaker) + { + SETSYMBOL(msp, gensym(";")); + break; + } + else + { + nexttarget = 0; + goto gotmess; + } + case A_COMMA: + if (target == &pd_objectmaker) + { + SETSYMBOL(msp, gensym(",")); + break; + } + else goto gotmess; + case A_FLOAT: + case A_SYMBOL: + *msp = *at; + break; + case A_DOLLAR: + if (at->a_w.w_index > 0 && at->a_w.w_index <= argc) + *msp = argv[at->a_w.w_index-1]; + else if (at->a_w.w_index == 0) + SETFLOAT(msp, canvas_getdollarzero()); + else + { + if (target == &pd_objectmaker) + SETFLOAT(msp, 0); + else + { + error("$%d: argument number out of range", + at->a_w.w_index); + SETFLOAT(msp, 0); + } + } + break; + case A_DOLLSYM: + s9 = binbuf_realizedollsym(at->a_w.w_symbol, argc, argv, + target == &pd_objectmaker); + if (!s9) + { + error("%s: argument number out of range", at->a_w.w_symbol->s_name); + SETSYMBOL(msp, at->a_w.w_symbol); + } + else SETSYMBOL(msp, s9); + break; + default: + bug("bad item in binbuf"); + goto broken; + } + msp++; + ac--; + at++; + nargs++; + } + gotmess: + if (nargs) + { + switch (mstack->a_type) + { + case A_SYMBOL: + typedmess(target, mstack->a_w.w_symbol, nargs-1, mstack+1); + break; + case A_FLOAT: + if (nargs == 1) pd_float(target, mstack->a_w.w_float); + else pd_list(target, 0, nargs, mstack); + break; + default: + break; + } + } + msp = mstack; + if (!ac) break; + target = nexttarget; + at++; + ac--; + } +broken: + if (maxnargs > SMALLMSG) + ATOMS_FREEA(mstack, maxnargs); +} + +int binbuf_read(t_binbuf *b, char *filename, char *dirname, int crflag) +{ + long length; + int fd; + int readret; + char *buf; + char namebuf[MAXPDSTRING]; + + if (*dirname) + snprintf(namebuf, MAXPDSTRING-1, "%s/%s", dirname, filename); + else + snprintf(namebuf, MAXPDSTRING-1, "%s", filename); + namebuf[MAXPDSTRING-1] = 0; + + if ((fd = sys_open(namebuf, 0)) < 0) + { + fprintf(stderr, "open: "); + perror(namebuf); + return (1); + } + if ((length = (long)lseek(fd, 0, SEEK_END)) < 0 || lseek(fd, 0, SEEK_SET) < 0 + || !(buf = t_getbytes(length))) + { + fprintf(stderr, "lseek: "); + perror(namebuf); + close(fd); + return(1); + } + if ((readret = (int)read(fd, buf, length)) < length) + { + fprintf(stderr, "read (%d %ld) -> %d\n", fd, length, readret); + perror(namebuf); + close(fd); + t_freebytes(buf, length); + return(1); + } + /* optionally map carriage return to semicolon */ + if (crflag) + { + int i; + for (i = 0; i < length; i++) + if (buf[i] == '\n') + buf[i] = ';'; + } + binbuf_text(b, buf, length); + +#if 0 + startpost("binbuf_read "); postatom(b->b_n, b->b_vec); endpost(); +#endif + + t_freebytes(buf, length); + close(fd); + return (0); +} + + /* read a binbuf from a file, via the search patch of a canvas */ +int binbuf_read_via_canvas(t_binbuf *b, char *filename, t_canvas *canvas, + int crflag) +{ + int filedesc; + char buf[MAXPDSTRING], *bufptr; + if ((filedesc = canvas_open(canvas, filename, "", + buf, &bufptr, MAXPDSTRING, 0)) < 0) + { + error("%s: can't open", filename); + return (1); + } + else close (filedesc); + if (binbuf_read(b, bufptr, buf, crflag)) + return (1); + else return (0); +} + + /* old version */ +int binbuf_read_via_path(t_binbuf *b, char *filename, char *dirname, + int crflag) +{ + int filedesc; + char buf[MAXPDSTRING], *bufptr; + if ((filedesc = open_via_path( + dirname, filename, "", buf, &bufptr, MAXPDSTRING, 0)) < 0) + { + error("%s: can't open", filename); + return (1); + } + else close (filedesc); + if (binbuf_read(b, bufptr, buf, crflag)) + return (1); + else return (0); +} + +#define WBUFSIZE 4096 +static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd); + + /* write a binbuf to a text file. If "crflag" is set we suppress + semicolons. */ +int binbuf_write(t_binbuf *x, char *filename, char *dir, int crflag) +{ + FILE *f = 0; + char sbuf[WBUFSIZE], fbuf[MAXPDSTRING], *bp = sbuf, *ep = sbuf + WBUFSIZE; + t_atom *ap; + int indx, deleteit = 0; + int ncolumn = 0; + + if (*dir) + snprintf(fbuf, MAXPDSTRING-1, "%s/%s", dir, filename); + else + snprintf(fbuf, MAXPDSTRING-1, "%s", filename); + fbuf[MAXPDSTRING-1] = 0; + + if (!strcmp(filename + strlen(filename) - 4, ".pat") || + !strcmp(filename + strlen(filename) - 4, ".mxt")) + { + x = binbuf_convert(x, 0); + deleteit = 1; + } + + if (!(f = sys_fopen(fbuf, "w"))) + { + fprintf(stderr, "open: "); + sys_unixerror(fbuf); + goto fail; + } + for (ap = x->b_vec, indx = x->b_n; indx--; ap++) + { + int length; + /* estimate how many characters will be needed. Printing out + symbols may need extra characters for inserting backslashes. */ + if (ap->a_type == A_SYMBOL || ap->a_type == A_DOLLSYM) + length = 80 + (int)strlen(ap->a_w.w_symbol->s_name); + else length = 40; + if (ep - bp < length) + { + if (fwrite(sbuf, bp-sbuf, 1, f) < 1) + { + sys_unixerror(fbuf); + goto fail; + } + bp = sbuf; + } + if ((ap->a_type == A_SEMI || ap->a_type == A_COMMA) && + bp > sbuf && bp[-1] == ' ') bp--; + if (!crflag || ap->a_type != A_SEMI) + { + atom_string(ap, bp, (unsigned int)((ep-bp)-2)); + length = (int)strlen(bp); + bp += length; + ncolumn += length; + } + if (ap->a_type == A_SEMI || (!crflag && ncolumn > 65)) + { + *bp++ = '\n'; + ncolumn = 0; + } + else + { + *bp++ = ' '; + ncolumn++; + } + } + if (fwrite(sbuf, bp-sbuf, 1, f) < 1) + { + sys_unixerror(fbuf); + goto fail; + } + + if (fflush(f) != 0) + { + sys_unixerror(fbuf); + goto fail; + } + + if (deleteit) + binbuf_free(x); + fclose(f); + return (0); +fail: + if (deleteit) + binbuf_free(x); + if (f) + fclose(f); + return (1); +} + +/* The following routine attempts to convert from max to pd or back. The +max to pd direction is working OK but you will need to make lots of +abstractions for objects like "gate" which don't exist in Pd. conversion +from Pd to Max hasn't been tested for patches with subpatches yet! */ + +#define MAXSTACK 1000 + +#define ISSYMBOL(a, b) ((a)->a_type == A_SYMBOL && \ + !strcmp((a)->a_w.w_symbol->s_name, (b))) + +static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd) +{ + t_binbuf *newb = binbuf_new(); + t_atom *vec = oldb->b_vec; + t_int n = oldb->b_n, nextindex, stackdepth = 0, stack[MAXSTACK] = {0}, + nobj = 0, gotfontsize = 0; + int i; + t_atom outmess[MAXSTACK], *nextmess; + t_float fontsize = 10; + if (!maxtopd) + binbuf_addv(newb, "ss;", gensym("max"), gensym("v2")); + for (nextindex = 0; nextindex < n; ) + { + int endmess, natom; + char *first, *second, *third; + for (endmess = (int)nextindex; endmess < n && vec[endmess].a_type != A_SEMI; + endmess++) + ; + if (endmess == n) break; + if (endmess == nextindex || endmess == nextindex + 1 + || vec[nextindex].a_type != A_SYMBOL || + vec[nextindex+1].a_type != A_SYMBOL) + { + nextindex = endmess + 1; + continue; + } + natom = endmess - (int)nextindex; + if (natom > MAXSTACK-10) natom = MAXSTACK-10; + nextmess = vec + nextindex; + first = nextmess->a_w.w_symbol->s_name; + second = (nextmess+1)->a_w.w_symbol->s_name; + if (maxtopd) + { + /* case 1: importing a ".pat" file into Pd. */ + + /* dollar signs in file translate to symbols */ + for (i = 0; i < natom; i++) + { + if (nextmess[i].a_type == A_DOLLAR) + { + char buf[100]; + sprintf(buf, "$%d", nextmess[i].a_w.w_index); + SETSYMBOL(nextmess+i, gensym(buf)); + } + else if (nextmess[i].a_type == A_DOLLSYM) + { + char buf[100]; + sprintf(buf, "%s", nextmess[i].a_w.w_symbol->s_name); + SETSYMBOL(nextmess+i, gensym(buf)); + } + } + if (!strcmp(first, "#N")) + { + if (!strcmp(second, "vpatcher")) + { + if (stackdepth >= MAXSTACK) + { + error("stack depth exceeded: too many embedded patches"); + return (newb); + } + stack[stackdepth] = nobj; + stackdepth++; + nobj = 0; + binbuf_addv(newb, "ssfffff;", + gensym("#N"), gensym("canvas"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + atom_getfloatarg(4, natom, nextmess) - + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(5, natom, nextmess) - + atom_getfloatarg(3, natom, nextmess), + (t_float)sys_defaultfont); + } + } + if (!strcmp(first, "#P")) + { + /* drop initial "hidden" flag */ + if (!strcmp(second, "hidden")) + { + nextmess++; + natom--; + second = (nextmess+1)->a_w.w_symbol->s_name; + } + if (natom >= 7 && !strcmp(second, "newobj") + && (ISSYMBOL(&nextmess[6], "patcher") || + ISSYMBOL(&nextmess[6], "p"))) + { + binbuf_addv(newb, "ssffss;", + gensym("#X"), gensym("restore"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + gensym("pd"), atom_getsymbolarg(7, natom, nextmess)); + if (stackdepth) stackdepth--; + nobj = stack[stackdepth]; + nobj++; + } + else if (!strcmp(second, "newex") || !strcmp(second, "newobj")) + { + t_symbol *classname = + atom_getsymbolarg(6, natom, nextmess); + if (classname == gensym("trigger") || + classname == gensym("t")) + { + for (i = 7; i < natom; i++) + if (nextmess[i].a_type == A_SYMBOL && + nextmess[i].a_w.w_symbol == gensym("i")) + nextmess[i].a_w.w_symbol = gensym("f"); + } + if (classname == gensym("table")) + classname = gensym("TABLE"); + SETSYMBOL(outmess, gensym("#X")); + SETSYMBOL(outmess + 1, gensym("obj")); + outmess[2] = nextmess[2]; + outmess[3] = nextmess[3]; + SETSYMBOL(outmess+4, classname); + for (i = 7; i < natom; i++) + outmess[i-2] = nextmess[i]; + SETSEMI(outmess + natom - 2); + binbuf_add(newb, natom - 1, outmess); + nobj++; + } + else if (!strcmp(second, "message") || + !strcmp(second, "comment")) + { + SETSYMBOL(outmess, gensym("#X")); + SETSYMBOL(outmess + 1, gensym( + (strcmp(second, "message") ? "text" : "msg"))); + outmess[2] = nextmess[2]; + outmess[3] = nextmess[3]; + for (i = 6; i < natom; i++) + outmess[i-2] = nextmess[i]; + SETSEMI(outmess + natom - 2); + binbuf_add(newb, natom - 1, outmess); + nobj++; + } + else if (!strcmp(second, "button")) + { + binbuf_addv(newb, "ssffs;", + gensym("#X"), gensym("obj"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + gensym("bng")); + nobj++; + } + else if (!strcmp(second, "number") || !strcmp(second, "flonum")) + { + binbuf_addv(newb, "ssff;", + gensym("#X"), gensym("floatatom"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess)); + nobj++; + } + else if (!strcmp(second, "slider")) + { + t_float inc = atom_getfloatarg(7, natom, nextmess); + if (inc <= 0) + inc = 1; + binbuf_addv(newb, "ssffsffffffsssfffffffff;", + gensym("#X"), gensym("obj"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + gensym("vsl"), + atom_getfloatarg(4, natom, nextmess), + atom_getfloatarg(5, natom, nextmess), + atom_getfloatarg(6, natom, nextmess), + atom_getfloatarg(6, natom, nextmess) + + (atom_getfloatarg(5, natom, nextmess) - 1) * inc, + 0., 0., + gensym("empty"), gensym("empty"), gensym("empty"), + 0., -8., 0., 8., -262144., -1., -1., 0., 1.); + nobj++; + } + else if (!strcmp(second, "toggle")) + { + binbuf_addv(newb, "ssffs;", + gensym("#X"), gensym("obj"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + gensym("tgl")); + nobj++; + } + else if (!strcmp(second, "inlet")) + { + binbuf_addv(newb, "ssffs;", + gensym("#X"), gensym("obj"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + gensym((natom > 5 ? "inlet~" : "inlet"))); + nobj++; + } + else if (!strcmp(second, "outlet")) + { + binbuf_addv(newb, "ssffs;", + gensym("#X"), gensym("obj"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + gensym((natom > 5 ? "outlet~" : "outlet"))); + nobj++; + } + else if (!strcmp(second, "user")) + { + third = (nextmess+2)->a_w.w_symbol->s_name; + if (!strcmp(third, "hslider")) + { + t_float range = atom_getfloatarg(7, natom, nextmess); + t_float multiplier = atom_getfloatarg(8, natom, nextmess); + t_float offset = atom_getfloatarg(9, natom, nextmess); + binbuf_addv(newb, "ssffsffffffsssfffffffff;", + gensym("#X"), gensym("obj"), + atom_getfloatarg(3, natom, nextmess), + atom_getfloatarg(4, natom, nextmess), + gensym("hsl"), + atom_getfloatarg(6, natom, nextmess), + atom_getfloatarg(5, natom, nextmess), + offset, + range + offset, + 0., 0., + gensym("empty"), gensym("empty"), gensym("empty"), + 0., -8., 0., 8., -262144., -1., -1., 0., 1.); + } + else if (!strcmp(third, "uslider")) + { + t_float range = atom_getfloatarg(7, natom, nextmess); + t_float multiplier = atom_getfloatarg(8, natom, nextmess); + t_float offset = atom_getfloatarg(9, natom, nextmess); + binbuf_addv(newb, "ssffsffffffsssfffffffff;", + gensym("#X"), gensym("obj"), + atom_getfloatarg(3, natom, nextmess), + atom_getfloatarg(4, natom, nextmess), + gensym("vsl"), + atom_getfloatarg(5, natom, nextmess), + atom_getfloatarg(6, natom, nextmess), + offset, + range + offset, + 0., 0., + gensym("empty"), gensym("empty"), gensym("empty"), + 0., -8., 0., 8., -262144., -1., -1., 0., 1.); + } + else + binbuf_addv(newb, "ssffs;", + gensym("#X"), gensym("obj"), + atom_getfloatarg(3, natom, nextmess), + atom_getfloatarg(4, natom, nextmess), + atom_getsymbolarg(2, natom, nextmess)); + nobj++; + } + else if (!strcmp(second, "connect")|| + !strcmp(second, "fasten")) + { + binbuf_addv(newb, "ssffff;", + gensym("#X"), gensym("connect"), + nobj - atom_getfloatarg(2, natom, nextmess) - 1, + atom_getfloatarg(3, natom, nextmess), + nobj - atom_getfloatarg(4, natom, nextmess) - 1, + atom_getfloatarg(5, natom, nextmess)); + } + } + } + else /* Pd to Max */ + { + if (!strcmp(first, "#N")) + { + if (!strcmp(second, "canvas")) + { + t_float x, y; + if (stackdepth >= MAXSTACK) + { + error("stack depth exceeded: too many embedded patches"); + return (newb); + } + stack[stackdepth] = nobj; + stackdepth++; + nobj = 0; + if(!gotfontsize) { /* only the first canvas sets the font size */ + fontsize = atom_getfloatarg(6, natom, nextmess); + gotfontsize = 1; + } + x = atom_getfloatarg(2, natom, nextmess); + y = atom_getfloatarg(3, natom, nextmess); + binbuf_addv(newb, "ssffff;", + gensym("#N"), gensym("vpatcher"), + x, y, + atom_getfloatarg(4, natom, nextmess) + x, + atom_getfloatarg(5, natom, nextmess) + y); + } + } + if (!strcmp(first, "#X")) + { + if (natom >= 5 && !strcmp(second, "restore") + && (ISSYMBOL (&nextmess[4], "pd"))) + { + binbuf_addv(newb, "ss;", gensym("#P"), gensym("pop")); + SETSYMBOL(outmess, gensym("#P")); + SETSYMBOL(outmess + 1, gensym("newobj")); + outmess[2] = nextmess[2]; + outmess[3] = nextmess[3]; + SETFLOAT(outmess + 4, 50.*(natom-5)); + SETFLOAT(outmess + 5, fontsize); + SETSYMBOL(outmess + 6, gensym("p")); + for (i = 5; i < natom; i++) + outmess[i+2] = nextmess[i]; + SETSEMI(outmess + natom + 2); + binbuf_add(newb, natom + 3, outmess); + if (stackdepth) stackdepth--; + nobj = stack[stackdepth]; + nobj++; + } + else if (!strcmp(second, "obj")) + { + t_symbol *classname = + atom_getsymbolarg(4, natom, nextmess); + if (classname == gensym("inlet")) + binbuf_addv(newb, "ssfff;", gensym("#P"), + gensym("inlet"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + 10. + fontsize); + else if (classname == gensym("inlet~")) + binbuf_addv(newb, "ssffff;", gensym("#P"), + gensym("inlet"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + 10. + fontsize, 1.); + else if (classname == gensym("outlet")) + binbuf_addv(newb, "ssfff;", gensym("#P"), + gensym("outlet"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + 10. + fontsize); + else if (classname == gensym("outlet~")) + binbuf_addv(newb, "ssffff;", gensym("#P"), + gensym("outlet"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + 10. + fontsize, 1.); + else if (classname == gensym("bng")) + binbuf_addv(newb, "ssffff;", gensym("#P"), + gensym("button"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + atom_getfloatarg(5, natom, nextmess), 0.); + else if (classname == gensym("tgl")) + binbuf_addv(newb, "ssffff;", gensym("#P"), + gensym("toggle"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + atom_getfloatarg(5, natom, nextmess), 0.); + else if (classname == gensym("vsl")) + binbuf_addv(newb, "ssffffff;", gensym("#P"), + gensym("slider"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + atom_getfloatarg(5, natom, nextmess), + atom_getfloatarg(6, natom, nextmess), + (atom_getfloatarg(8, natom, nextmess) - + atom_getfloatarg(7, natom, nextmess)) / + (atom_getfloatarg(6, natom, nextmess) == 1? 1 : + atom_getfloatarg(6, natom, nextmess) - 1), + atom_getfloatarg(7, natom, nextmess)); + else if (classname == gensym("hsl")) + { + t_float slmin = atom_getfloatarg(7, natom, nextmess); + t_float slmax = atom_getfloatarg(8, natom, nextmess); + binbuf_addv(newb, "sssffffffff;", gensym("#P"), + gensym("user"), + gensym("hslider"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + atom_getfloatarg(6, natom, nextmess), + atom_getfloatarg(5, natom, nextmess), + slmax - slmin + 1, /* range */ + 1., /* multiplier */ + slmin, /* offset */ + 0.); + } + else if ( (classname == gensym("trigger")) || + (classname == gensym("t")) ) + { + t_symbol *arg; + SETSYMBOL(outmess, gensym("#P")); + SETSYMBOL(outmess + 1, gensym("newex")); + outmess[2] = nextmess[2]; + outmess[3] = nextmess[3]; + SETFLOAT(outmess + 4, 50.*(natom-4)); + SETFLOAT(outmess + 5, fontsize); + outmess[6] = nextmess[4]; + for (i = 5; i < natom; i++) { + arg = atom_getsymbolarg(i, natom, nextmess); + if (arg == gensym("a")) + SETSYMBOL(outmess + i + 2, gensym("l")); + else if (arg == gensym("anything")) + SETSYMBOL(outmess + i + 2, gensym("l")); + else if (arg == gensym("bang")) + SETSYMBOL(outmess + i + 2, gensym("b")); + else if (arg == gensym("float")) + SETSYMBOL(outmess + i + 2, gensym("f")); + else if (arg == gensym("list")) + SETSYMBOL(outmess + i + 2, gensym("l")); + else if (arg == gensym("symbol")) + SETSYMBOL(outmess + i + 2, gensym("s")); + else + outmess[i+2] = nextmess[i]; + } + SETSEMI(outmess + natom + 2); + binbuf_add(newb, natom + 3, outmess); + } + else + { + SETSYMBOL(outmess, gensym("#P")); + SETSYMBOL(outmess + 1, gensym("newex")); + outmess[2] = nextmess[2]; + outmess[3] = nextmess[3]; + SETFLOAT(outmess + 4, 50.*(natom-4)); + SETFLOAT(outmess + 5, fontsize); + for (i = 4; i < natom; i++) + outmess[i+2] = nextmess[i]; + if (classname == gensym("osc~")) + SETSYMBOL(outmess + 6, gensym("cycle~")); + SETSEMI(outmess + natom + 2); + binbuf_add(newb, natom + 3, outmess); + } + nobj++; + + } + else if (!strcmp(second, "msg") || + !strcmp(second, "text")) + { + SETSYMBOL(outmess, gensym("#P")); + SETSYMBOL(outmess + 1, gensym( + (strcmp(second, "msg") ? "comment" : "message"))); + outmess[2] = nextmess[2]; + outmess[3] = nextmess[3]; + SETFLOAT(outmess + 4, 50.*(natom-4)); + SETFLOAT(outmess + 5, fontsize); + for (i = 4; i < natom; i++) + outmess[i+2] = nextmess[i]; + SETSEMI(outmess + natom + 2); + binbuf_add(newb, natom + 3, outmess); + nobj++; + } + else if (!strcmp(second, "floatatom")) + { + t_float width = atom_getfloatarg(4, natom, nextmess)*fontsize; + if(width<8) width = 150; /* if pd width=0, set it big */ + binbuf_addv(newb, "ssfff;", + gensym("#P"), gensym("flonum"), + atom_getfloatarg(2, natom, nextmess), + atom_getfloatarg(3, natom, nextmess), + width); + nobj++; + } + else if (!strcmp(second, "connect")) + { + binbuf_addv(newb, "ssffff;", + gensym("#P"), gensym("connect"), + nobj - atom_getfloatarg(2, natom, nextmess) - 1, + atom_getfloatarg(3, natom, nextmess), + nobj - atom_getfloatarg(4, natom, nextmess) - 1, + atom_getfloatarg(5, natom, nextmess)); + } + } + } + nextindex = endmess + 1; + } + if (!maxtopd) + binbuf_addv(newb, "ss;", gensym("#P"), gensym("pop")); +#if 0 + binbuf_write(newb, "import-result.pd", "/tmp", 0); +#endif + return (newb); +} + +void pd_doloadbang(void); + +/* LATER make this evaluate the file on-the-fly. */ +/* LATER figure out how to log errors */ +void binbuf_evalfile(t_symbol *name, t_symbol *dir) +{ + t_binbuf *b = binbuf_new(); + int import = !strcmp(name->s_name + strlen(name->s_name) - 4, ".pat") || + !strcmp(name->s_name + strlen(name->s_name) - 4, ".mxt"); + int dspstate = canvas_suspend_dsp(); + /* set filename so that new canvases can pick them up */ + glob_setfilename(0, name, dir); + if (binbuf_read(b, name->s_name, dir->s_name, 0)) + error("%s: read failed; %s", name->s_name, strerror(errno)); + else + { + /* save bindings of symbols #N, #A (and restore afterward) */ + t_pd *bounda = gensym("#A")->s_thing, *boundn = s__N.s_thing; + gensym("#A")->s_thing = 0; + s__N.s_thing = &pd_canvasmaker; + if (import) + { + t_binbuf *newb = binbuf_convert(b, 1); + binbuf_free(b); + b = newb; + } + binbuf_eval(b, 0, 0, 0); + /* avoid crashing if no canvas was created by binbuf eval */ + if (s__X.s_thing && *s__X.s_thing == canvas_class) + canvas_initbang((t_canvas *)(s__X.s_thing)); /* JMZ*/ + gensym("#A")->s_thing = bounda; + s__N.s_thing = boundn; + } + glob_setfilename(0, &s_, &s_); + binbuf_free(b); + canvas_resume_dsp(dspstate); +} + +t_pd *glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir) +{ + t_pd *x = 0; + /* even though binbuf_evalfile appears to take care of dspstate, + we have to do it again here, because canvas_startdsp() assumes + that all toplevel canvases are visible. LATER check if this + is still necessary -- probably not. */ + + int dspstate = canvas_suspend_dsp(); + t_pd *boundx = s__X.s_thing; + s__X.s_thing = 0; /* don't save #X; we'll need to leave it bound + for the caller to grab it. */ + binbuf_evalfile(name, dir); + while ((x != s__X.s_thing) && s__X.s_thing) + { + x = s__X.s_thing; + vmess(x, gensym("pop"), "i", 1); + } + if (!sys_noloadbang) + pd_doloadbang(); + canvas_resume_dsp(dspstate); + s__X.s_thing = boundx; + return x; +} + + /* save a text object to a binbuf for a file or copy buf */ +void binbuf_savetext(t_binbuf *bfrom, t_binbuf *bto) +{ + int k, n = binbuf_getnatom(bfrom); + t_atom *ap = binbuf_getvec(bfrom), at; + for (k = 0; k < n; k++) + { + if (ap[k].a_type == A_FLOAT || + (ap[k].a_type == A_SYMBOL && + !strchr(ap[k].a_w.w_symbol->s_name, ';') && + !strchr(ap[k].a_w.w_symbol->s_name, ',') && + !strchr(ap[k].a_w.w_symbol->s_name, '$'))) + binbuf_add(bto, 1, &ap[k]); + else + { + char buf[MAXPDSTRING+1]; + atom_string(&ap[k], buf, MAXPDSTRING); + SETSYMBOL(&at, gensym(buf)); + binbuf_add(bto, 1, &at); + } + } + binbuf_addsemi(bto); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/m_class.c b/ports/camomile/source/LibPd/pure-data/src/m_class.c new file mode 100644 index 00000000..6c3a7a3c --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/m_class.c @@ -0,0 +1,1080 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#define PD_CLASS_DEF +#include "m_pd.h" +#include "m_imp.h" +#include "s_stuff.h" +#include "g_canvas.h" +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef _WIN32 +#include +#endif + +#include +#include +#include + +#ifdef _MSC_VER /* This is only for Microsoft's compiler, not cygwin, e.g. */ +#define snprintf _snprintf +#endif + +static t_symbol *class_loadsym; /* name under which an extern is invoked */ +static void pd_defaultfloat(t_pd *x, t_float f); +static void pd_defaultlist(t_pd *x, t_symbol *s, int argc, t_atom *argv); +t_pd pd_objectmaker; /* factory for creating "object" boxes */ +t_pd pd_canvasmaker; /* factory for creating canvases */ + +static t_symbol *class_extern_dir; + +#ifdef PDINSTANCE +static t_class *class_list = 0; +PERTHREAD t_pdinstance *pd_this; +t_pdinstance **pd_instances; +int pd_ninstances; +#else +t_symbol s_pointer, s_float, s_symbol, s_bang, s_list, s_anything, + s_signal, s__N, s__X, s_x, s_y, s_; +#endif +t_pdinstance pd_maininstance; + +static t_symbol *dogensym(const char *s, t_symbol *oldsym, + t_pdinstance *pdinstance); +void x_midi_newpdinstance( void); +void x_midi_freepdinstance( void); +void s_inter_newpdinstance( void); +void s_inter_freepdinstance( void); +void g_canvas_newpdinstance( void); +void g_canvas_freepdinstance( void); +void d_ugen_newpdinstance( void); +void d_ugen_freepdinstance( void); + +void s_stuff_newpdinstance( void) +{ + STUFF = getbytes(sizeof(*STUFF)); + STUFF->st_externlist = STUFF->st_searchpath = + STUFF->st_staticpath = STUFF->st_helppath = 0; + STUFF->st_schedblocksize = STUFF->st_blocksize = DEFDACBLKSIZE; +} + +void s_stuff_freepdinstance( void) +{ + freebytes(STUFF, sizeof(*STUFF)); +} + +static t_pdinstance *pdinstance_init(t_pdinstance *x) +{ + int i; + x->pd_systime = 0; + x->pd_clock_setlist = 0; + x->pd_canvaslist = 0; + x->pd_symhash = getbytes(SYMTABHASHSIZE * sizeof(*x->pd_symhash)); + for (i = 0; i < SYMTABHASHSIZE; i++) + x->pd_symhash[i] = 0; +#ifdef PDINSTANCE + dogensym("pointer", &x->pd_s_pointer, x); + dogensym("float", &x->pd_s_float, x); + dogensym("symbol", &x->pd_s_symbol, x); + dogensym("bang", &x->pd_s_bang, x); + dogensym("list", &x->pd_s_list, x); + dogensym("anything", &x->pd_s_anything, x); + dogensym("signal", &x->pd_s_signal, x); + dogensym("#N", &x->pd_s__N, x); + dogensym("#X", &x->pd_s__X, x); + dogensym("x", &x->pd_s_x, x); + dogensym("y", &x->pd_s_y, x); + dogensym("", &x->pd_s_, x); + pd_this = x; +#else + dogensym("pointer", &s_pointer, x); + dogensym("float", &s_float, x); + dogensym("symbol", &s_symbol, x); + dogensym("bang", &s_bang, x); + dogensym("list", &s_list, x); + dogensym("anything", &s_anything, x); + dogensym("signal", &s_signal, x); + dogensym("#N", &s__N, x); + dogensym("#X", &s__X, x); + dogensym("x", &s_x, x); + dogensym("y", &s_y, x); + dogensym("", &s_, x); +#endif + x_midi_newpdinstance(); + g_canvas_newpdinstance(); + d_ugen_newpdinstance(); + s_stuff_newpdinstance(); + return (x); +} + +static void class_addmethodtolist(t_class *c, t_methodentry **methodlist, + int nmethod, t_gotfn fn, t_symbol *sel, t_atomtype *args, + t_pdinstance *pdinstance) +{ + int i; + t_methodentry *m; + for (i = 0; i < nmethod; i++) + if ((*methodlist)[i].me_name == sel) + { + char nbuf[80]; + snprintf(nbuf, 80, "%s_aliased", sel->s_name); + nbuf[79] = 0; + (*methodlist)[i].me_name = dogensym(nbuf, 0, pdinstance); + if (c == pd_objectmaker) + verbose(1, "warning: class '%s' overwritten; old one renamed '%s'", + sel->s_name, nbuf); + else verbose(1, "warning: old method '%s' for class '%s' renamed '%s'", + sel->s_name, c->c_name->s_name, nbuf); + } + (*methodlist) = t_resizebytes((*methodlist), + nmethod * sizeof(**methodlist), + (nmethod + 1) * sizeof(**methodlist)); + m = (*methodlist) + nmethod; + m->me_name = sel; + m->me_fun = (t_gotfn)fn; + i = 0; + while ((m->me_arg[i] = args[i])) + i++; +} + +#ifdef PDINSTANCE +EXTERN void pd_setinstance(t_pdinstance *x) +{ + pd_this = x; +} + +static void pdinstance_renumber(void) +{ + int i; + for (i = 0; i < pd_ninstances; i++) + pd_instances[i]->pd_instanceno = i; +} + +extern void text_template_init(void); +extern void garray_init(void); + +EXTERN t_pdinstance *pdinstance_new(void) +{ + t_pdinstance *x = (t_pdinstance *)getbytes(sizeof(t_pdinstance)); + t_class *c; + int i; + pd_this = x; + s_inter_newpdinstance(); + pdinstance_init(x); + sys_lock(); + pd_globallock(); + pd_instances = (t_pdinstance **)resizebytes(pd_instances, + pd_ninstances * sizeof(*pd_instances), + (pd_ninstances+1) * sizeof(*pd_instances)); + pd_instances[pd_ninstances] = x; + for (c = class_list; c; c = c->c_next) + { + c->c_methods = (t_methodentry **)t_resizebytes(c->c_methods, + pd_ninstances * sizeof(*c->c_methods), + (pd_ninstances + 1) * sizeof(*c->c_methods)); + c->c_methods[pd_ninstances] = t_getbytes(0); + for (i = 0; i < c->c_nmethod; i++) + class_addmethodtolist(c, &c->c_methods[pd_ninstances], i, + c->c_methods[0][i].me_fun, + dogensym(c->c_methods[0][i].me_name->s_name, 0, x), + c->c_methods[0][i].me_arg, x); + } + pd_ninstances++; + pdinstance_renumber(); + pd_bind(&glob_pdobject, gensym("pd")); + text_template_init(); + garray_init(); + pd_globalunlock(); + sys_unlock(); + return (x); +} + +EXTERN void pdinstance_free(t_pdinstance *x) +{ + t_symbol *s; + t_canvas *canvas; + int i, instanceno = x->pd_instanceno; + t_class *c; + pd_setinstance(x); + sys_lock(); + pd_globallock(); + + canvas_suspend_dsp(); + while (x->pd_canvaslist) + pd_free((t_pd *)x->pd_canvaslist); + for (c = class_list; c; c = c->c_next) + { + c->c_methods = (t_methodentry **)t_resizebytes(c->c_methods, + pd_ninstances * sizeof(*c->c_methods), + (pd_ninstances + 1) * sizeof(*c->c_methods)); + c->c_methods[pd_ninstances] = t_getbytes(0); + for (i = 0; i < c->c_nmethod; i++) + class_addmethodtolist(c, &c->c_methods[pd_ninstances], i, + c->c_methods[0][i].me_fun, + dogensym(c->c_methods[0][i].me_name->s_name, 0, x), + c->c_methods[0][i].me_arg, x); + } + for (i =0; i < SYMTABHASHSIZE; i++) + { + while ((s = x->pd_symhash[i])) + { + x->pd_symhash[i] = s->s_next; + if(s != &x->pd_s_pointer && + s != &x->pd_s_float && + s != &x->pd_s_symbol && + s != &x->pd_s_bang && + s != &x->pd_s_list && + s != &x->pd_s_anything && + s != &x->pd_s_signal && + s != &x->pd_s__N && + s != &x->pd_s__X && + s != &x->pd_s_x && + s != &x->pd_s_y && + s != &x->pd_s_) + freebytes(s, sizeof(*s)); + } + } + freebytes(x->pd_symhash, SYMTABHASHSIZE * sizeof (*x->pd_symhash)); + x_midi_freepdinstance(); + g_canvas_freepdinstance(); + d_ugen_freepdinstance(); + s_stuff_freepdinstance(); + s_inter_freepdinstance(); + for (i = instanceno; i < pd_ninstances-1; i++) + pd_instances[i] = pd_instances[i+1]; + pd_instances = (t_pdinstance **)resizebytes(pd_instances, + pd_ninstances * sizeof(*pd_instances), + (pd_ninstances-1) * sizeof(*pd_instances)); + pd_ninstances--; + pdinstance_renumber(); + pd_globalunlock(); + sys_unlock(); + pd_setinstance(&pd_maininstance); +} + +#endif /* PDINSTANCE */ + +static void pd_defaultanything(t_pd *x, t_symbol *s, int argc, t_atom *argv) +{ + pd_error(x, "%s: no method for '%s'", (*x)->c_name->s_name, s->s_name); +} + +static void pd_defaultbang(t_pd *x) +{ + if (*(*x)->c_listmethod != pd_defaultlist) + (*(*x)->c_listmethod)(x, 0, 0, 0); + else (*(*x)->c_anymethod)(x, &s_bang, 0, 0); +} + + /* am empty list calls the 'bang' method unless it's the default + bang method -- that might turn around and call our 'list' method + which could be an infinite recorsion. Fall through to calling our + 'anything' method. That had better not turn around and call us with + an empty list. */ +void pd_emptylist(t_pd *x) +{ + if (*(*x)->c_bangmethod != pd_defaultbang) + (*(*x)->c_bangmethod)(x); + else (*(*x)->c_anymethod)(x, &s_bang, 0, 0); +} + +static void pd_defaultpointer(t_pd *x, t_gpointer *gp) +{ + if (*(*x)->c_listmethod != pd_defaultlist) + { + t_atom at; + SETPOINTER(&at, gp); + (*(*x)->c_listmethod)(x, 0, 1, &at); + } + else + { + t_atom at; + SETPOINTER(&at, gp); + (*(*x)->c_anymethod)(x, &s_pointer, 1, &at); + } +} + +static void pd_defaultfloat(t_pd *x, t_float f) +{ + if (*(*x)->c_listmethod != pd_defaultlist) + { + t_atom at; + SETFLOAT(&at, f); + (*(*x)->c_listmethod)(x, 0, 1, &at); + } + else + { + t_atom at; + SETFLOAT(&at, f); + (*(*x)->c_anymethod)(x, &s_float, 1, &at); + } +} + +static void pd_defaultsymbol(t_pd *x, t_symbol *s) +{ + if (*(*x)->c_listmethod != pd_defaultlist) + { + t_atom at; + SETSYMBOL(&at, s); + (*(*x)->c_listmethod)(x, 0, 1, &at); + } + else + { + t_atom at; + SETSYMBOL(&at, s); + (*(*x)->c_anymethod)(x, &s_symbol, 1, &at); + } +} + +void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv); +static void class_nosavefn(t_gobj *z, t_binbuf *b); + + /* handle "list" messages to Pds without explicit list methods defined. */ +static void pd_defaultlist(t_pd *x, t_symbol *s, int argc, t_atom *argv) +{ + /* a list with no elements is handled by the 'bang' method if + one exists. */ + if (argc == 0 && *(*x)->c_bangmethod != pd_defaultbang) + { + (*(*x)->c_bangmethod)(x); + return; + } + /* a list with one element which is a number can be handled by a + "float" method if any is defined; same for "symbol", "pointer". */ + if (argc == 1) + { + if (argv->a_type == A_FLOAT && + *(*x)->c_floatmethod != pd_defaultfloat) + { + (*(*x)->c_floatmethod)(x, argv->a_w.w_float); + return; + } + else if (argv->a_type == A_SYMBOL && + *(*x)->c_symbolmethod != pd_defaultsymbol) + { + (*(*x)->c_symbolmethod)(x, argv->a_w.w_symbol); + return; + } + else if (argv->a_type == A_POINTER && + *(*x)->c_pointermethod != pd_defaultpointer) + { + (*(*x)->c_pointermethod)(x, argv->a_w.w_gpointer); + return; + } + } + /* Next try for an "anything" method */ + if ((*x)->c_anymethod != pd_defaultanything) + (*(*x)->c_anymethod)(x, &s_list, argc, argv); + + /* if the object is patchable (i.e., can have proper inlets) + send it on to obj_list which will unpack the list into the inlets */ + else if ((*x)->c_patchable) + obj_list((t_object *)x, s, argc, argv); + /* otherwise gove up and complain. */ + else pd_defaultanything(x, &s_list, argc, argv); +} + + /* for now we assume that all "gobjs" are text unless explicitly + overridden later by calling class_setbehavior(). I'm not sure + how to deal with Pds that aren't gobjs; shouldn't there be a + way to check that at run time? Perhaps the presence of a "newmethod" + should be our cue, or perhaps the "tiny" flag. */ + + /* another matter. This routine does two unrelated things: it creates + a Pd class, but also adds a "new" method to create an instance of it. + These are combined for historical reasons and for brevity in writing + objects. To avoid adding a "new" method send a null function pointer. + To add additional ones, use class_addcreator below. Some "classes", like + "select", are actually two classes of the same name, one for the single- + argument form, one for the multiple one; see select_setup() to find out + how this is handled. */ + +extern void text_save(t_gobj *z, t_binbuf *b); + +t_class *class_new(t_symbol *s, t_newmethod newmethod, t_method freemethod, + size_t size, int flags, t_atomtype type1, ...) +{ + va_list ap; + t_atomtype vec[MAXPDARG+1], *vp = vec; + int count = 0, i; + t_class *c; + int typeflag = flags & CLASS_TYPEMASK; + if (!typeflag) typeflag = CLASS_PATCHABLE; + *vp = type1; + + va_start(ap, type1); + while (*vp) + { + if (count == MAXPDARG) + { + error("class %s: sorry: only %d args typechecked; use A_GIMME", + s->s_name, MAXPDARG); + break; + } + vp++; + count++; + *vp = va_arg(ap, t_atomtype); + } + va_end(ap); + + if (pd_objectmaker && newmethod) + { + /* add a "new" method by the name specified by the object */ + class_addmethod(pd_objectmaker, (t_method)newmethod, s, + vec[0], vec[1], vec[2], vec[3], vec[4], vec[5]); + if (class_loadsym) + { + /* if we're loading an extern it might have been invoked by a + longer file name; in this case, make this an admissible name + too. */ + char *loadstring = class_loadsym->s_name, + l1 = strlen(s->s_name), l2 = strlen(loadstring); + if (l2 > l1 && !strcmp(s->s_name, loadstring + (l2 - l1))) + class_addmethod(pd_objectmaker, (t_method)newmethod, + class_loadsym, + vec[0], vec[1], vec[2], vec[3], vec[4], vec[5]); + } + } + c = (t_class *)t_getbytes(sizeof(*c)); + c->c_name = c->c_helpname = s; + c->c_size = size; + c->c_nmethod = 0; + c->c_freemethod = (t_method)freemethod; + c->c_bangmethod = pd_defaultbang; + c->c_pointermethod = pd_defaultpointer; + c->c_floatmethod = pd_defaultfloat; + c->c_symbolmethod = pd_defaultsymbol; + c->c_listmethod = pd_defaultlist; + c->c_anymethod = pd_defaultanything; + c->c_wb = (typeflag == CLASS_PATCHABLE ? &text_widgetbehavior : 0); + c->c_pwb = 0; + c->c_firstin = ((flags & CLASS_NOINLET) == 0); + c->c_patchable = (typeflag == CLASS_PATCHABLE); + c->c_gobj = (typeflag >= CLASS_GOBJ); + c->c_drawcommand = 0; + c->c_floatsignalin = 0; + c->c_externdir = class_extern_dir; + c->c_savefn = (typeflag == CLASS_PATCHABLE ? text_save : class_nosavefn); +#if PDINSTANCE + c->c_methods = (t_methodentry **)t_getbytes( + pd_ninstances * sizeof(*c->c_methods)); + for (i = 0; i < pd_ninstances; i++) + c->c_methods[i] = t_getbytes(0); + c->c_next = class_list; + class_list = c; +#else + c->c_methods = t_getbytes(0); +#endif +#if 0 /* enable this if you want to see a list of all classes */ + post("class: %s", c->c_name->s_name); +#endif + return (c); +} + + /* add a creation method, which is a function that returns a Pd object + suitable for putting in an object box. We presume you've got a class it + can belong to, but this won't be used until the newmethod is actually + called back (and the new method explicitly takes care of this.) */ + +void class_addcreator(t_newmethod newmethod, t_symbol *s, + t_atomtype type1, ...) +{ + va_list ap; + t_atomtype vec[MAXPDARG+1], *vp = vec; + int count = 0; + *vp = type1; + + va_start(ap, type1); + while (*vp) + { + if (count == MAXPDARG) + { + error("class %s: sorry: only %d creation args allowed", + s->s_name, MAXPDARG); + break; + } + vp++; + count++; + *vp = va_arg(ap, t_atomtype); + } + va_end(ap); + class_addmethod(pd_objectmaker, (t_method)newmethod, s, + vec[0], vec[1], vec[2], vec[3], vec[4], vec[5]); +} + +void class_addmethod(t_class *c, t_method fn, t_symbol *sel, + t_atomtype arg1, ...) +{ + va_list ap; + t_methodentry *m; + t_atomtype argtype = arg1; + int nargs, i; + + va_start(ap, arg1); + /* "signal" method specifies that we take audio signals but + that we don't want automatic float to signal conversion. This + is obsolete; you should now use the CLASS_MAINSIGNALIN macro. */ + if (sel == &s_signal) + { + if (c->c_floatsignalin) + post("warning: signal method overrides class_mainsignalin"); + c->c_floatsignalin = -1; + } + /* check for special cases. "Pointer" is missing here so that + pd_objectmaker's pointer method can be typechecked differently. */ + if (sel == &s_bang) + { + if (argtype) goto phooey; + class_addbang(c, fn); + } + else if (sel == &s_float) + { + if (argtype != A_FLOAT || va_arg(ap, t_atomtype)) goto phooey; + class_doaddfloat(c, fn); + } + else if (sel == &s_symbol) + { + if (argtype != A_SYMBOL || va_arg(ap, t_atomtype)) goto phooey; + class_addsymbol(c, fn); + } + else if (sel == &s_list) + { + if (argtype != A_GIMME) goto phooey; + class_addlist(c, fn); + } + else if (sel == &s_anything) + { + if (argtype != A_GIMME) goto phooey; + class_addanything(c, fn); + } + else + { + t_atomtype argvec[MAXPDARG+1]; + nargs = 0; + while (argtype != A_NULL && nargs < MAXPDARG) + { + argvec[nargs++] = argtype; + argtype = va_arg(ap, t_atomtype); + } + if (argtype != A_NULL) + error("%s_%s: only 5 arguments are typecheckable; use A_GIMME", + c->c_name->s_name, sel->s_name); + argvec[nargs] = 0; +#ifdef PDINSTANCE + for (i = 0; i < pd_ninstances; i++) + { + class_addmethodtolist(c, &c->c_methods[i], c->c_nmethod, + (t_gotfn)fn, dogensym(sel->s_name, 0, pd_instances[i]), + argvec, pd_instances[i]); + } +#else + class_addmethodtolist(c, &c->c_methods, c->c_nmethod, + (t_gotfn)fn, sel, argvec, &pd_maininstance); +#endif + c->c_nmethod++; + } + goto done; +phooey: + bug("class_addmethod: %s_%s: bad argument types\n", + c->c_name->s_name, sel->s_name); +done: + va_end(ap); + return; +} + + /* Instead of these, see the "class_addfloat", etc., macros in m_pd.h */ +void class_addbang(t_class *c, t_method fn) +{ + c->c_bangmethod = (t_bangmethod)fn; +} + +void class_addpointer(t_class *c, t_method fn) +{ + c->c_pointermethod = (t_pointermethod)fn; +} + +void class_doaddfloat(t_class *c, t_method fn) +{ + c->c_floatmethod = (t_floatmethod)fn; +} + +void class_addsymbol(t_class *c, t_method fn) +{ + c->c_symbolmethod = (t_symbolmethod)fn; +} + +void class_addlist(t_class *c, t_method fn) +{ + c->c_listmethod = (t_listmethod)fn; +} + +void class_addanything(t_class *c, t_method fn) +{ + c->c_anymethod = (t_anymethod)fn; +} + +void class_setwidget(t_class *c, const t_widgetbehavior *w) +{ + c->c_wb = w; +} + +void class_setparentwidget(t_class *c, const t_parentwidgetbehavior *pw) +{ + c->c_pwb = pw; +} + +char *class_getname(t_class *c) +{ + return (c->c_name->s_name); +} + +char *class_gethelpname(t_class *c) +{ + return (c->c_helpname->s_name); +} + +void class_sethelpsymbol(t_class *c, t_symbol *s) +{ + c->c_helpname = s; +} + +const t_parentwidgetbehavior *pd_getparentwidget(t_pd *x) +{ + return ((*x)->c_pwb); +} + +void class_setdrawcommand(t_class *c) +{ + c->c_drawcommand = 1; +} + +int class_isdrawcommand(t_class *c) +{ + return (c->c_drawcommand); +} + +static void pd_floatforsignal(t_pd *x, t_float f) +{ + int offset = (*x)->c_floatsignalin; + if (offset > 0) + *(t_float *)(((char *)x) + offset) = f; + else + pd_error(x, "%s: float unexpected for signal input", + (*x)->c_name->s_name); +} + +void class_domainsignalin(t_class *c, int onset) +{ + if (onset <= 0) onset = -1; + else + { + if (c->c_floatmethod != pd_defaultfloat) + post("warning: %s: float method overwritten", c->c_name->s_name); + c->c_floatmethod = (t_floatmethod)pd_floatforsignal; + } + c->c_floatsignalin = onset; +} + +void class_set_extern_dir(t_symbol *s) +{ + class_extern_dir = s; +} + +char *class_gethelpdir(t_class *c) +{ + return (c->c_externdir->s_name); +} + +static void class_nosavefn(t_gobj *z, t_binbuf *b) +{ + bug("save function called but not defined"); +} + +void class_setsavefn(t_class *c, t_savefn f) +{ + c->c_savefn = f; +} + +t_savefn class_getsavefn(t_class *c) +{ + return (c->c_savefn); +} + +void class_setpropertiesfn(t_class *c, t_propertiesfn f) +{ + c->c_propertiesfn = f; +} + +t_propertiesfn class_getpropertiesfn(t_class *c) +{ + return (c->c_propertiesfn); +} + +/* ---------------- the symbol table ------------------------ */ + +static t_symbol *dogensym(const char *s, t_symbol *oldsym, + t_pdinstance *pdinstance) +{ + t_symbol **sym1, *sym2; + unsigned int hash = 5381; + int length = 0; + const char *s2 = s; + while (*s2) /* djb2 hash algo */ + { + hash = ((hash << 5) + hash) + *s2; + length++; + s2++; + } + sym1 = pdinstance->pd_symhash + (hash & (SYMTABHASHSIZE-1)); + while ((sym2 = *sym1)) + { + if (!strcmp(sym2->s_name, s)) return(sym2); + sym1 = &sym2->s_next; + } + if (oldsym) + sym2 = oldsym; + else sym2 = (t_symbol *)t_getbytes(sizeof(*sym2)); + sym2->s_name = t_getbytes(length+1); + sym2->s_next = 0; + sym2->s_thing = 0; + strcpy(sym2->s_name, s); + *sym1 = sym2; + return (sym2); +} + +t_symbol *gensym(const char *s) +{ + return(dogensym(s, 0, pd_this)); +} + +static t_symbol *addfileextent(t_symbol *s) +{ + char namebuf[MAXPDSTRING], *str = s->s_name; + int ln = (int)strlen(str); + if (!strcmp(str + ln - 3, ".pd")) return (s); + strcpy(namebuf, str); + strcpy(namebuf+ln, ".pd"); + return (gensym(namebuf)); +} + +#define MAXOBJDEPTH 1000 +static int tryingalready; + +void canvas_popabstraction(t_canvas *x); + +t_symbol* pathsearch(t_symbol *s,char* ext); +int pd_setloadingabstraction(t_symbol *sym); + + /* this routine is called when a new "object" is requested whose class Pd + doesn't know. Pd tries to load it as an extern, then as an abstraction. */ +void new_anything(void *dummy, t_symbol *s, int argc, t_atom *argv) +{ + int fd; + char dirbuf[MAXPDSTRING], classslashclass[MAXPDSTRING], *nameptr; + if (tryingalready>MAXOBJDEPTH){ + error("maximum object loading depth %d reached", MAXOBJDEPTH); + return; + } + pd_this->pd_newest = 0; + class_loadsym = s; + pd_globallock(); + if (sys_load_lib(canvas_getcurrent(), s->s_name)) + { + tryingalready++; + typedmess(dummy, s, argc, argv); + tryingalready--; + return; + } + class_loadsym = 0; + pd_globalunlock(); +} + +void mess_init(void) +{ + if (pd_objectmaker) + return; +#ifdef PDINSTANCE + pd_this = &pd_maininstance; +#endif + s_inter_newpdinstance(); + sys_lock(); + pd_globallock(); + pdinstance_init(&pd_maininstance); + class_extern_dir = &s_; + pd_objectmaker = class_new(gensym("objectmaker"), 0, 0, sizeof(t_pd), + CLASS_DEFAULT, A_NULL); + pd_canvasmaker = class_new(gensym("canvasmaker"), 0, 0, sizeof(t_pd), + CLASS_DEFAULT, A_NULL); + class_addanything(pd_objectmaker, (t_method)new_anything); + pd_globalunlock(); + sys_unlock(); +} + +/* This is externally available, but note that it might later disappear; the +whole "newest" thing is a hack which needs to be redesigned. */ +t_pd *pd_newest(void) +{ + return (pd_this->pd_newest); +} + + /* horribly, we need prototypes for each of the artificial function + calls in typedmess(), to keep the compiler quiet. */ +typedef t_pd *(*t_newgimme)(t_symbol *s, int argc, t_atom *argv); +typedef void(*t_messgimme)(t_pd *x, t_symbol *s, int argc, t_atom *argv); + +typedef t_pd *(*t_fun0)( + t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5); +typedef t_pd *(*t_fun1)(t_int i1, + t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5); +typedef t_pd *(*t_fun2)(t_int i1, t_int i2, + t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5); +typedef t_pd *(*t_fun3)(t_int i1, t_int i2, t_int i3, + t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5); +typedef t_pd *(*t_fun4)(t_int i1, t_int i2, t_int i3, t_int i4, + t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5); +typedef t_pd *(*t_fun5)(t_int i1, t_int i2, t_int i3, t_int i4, t_int i5, + t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5); +typedef t_pd *(*t_fun6)(t_int i1, t_int i2, t_int i3, t_int i4, t_int i5, t_int i6, + t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5); + +void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv) +{ + t_method *f; + t_class *c = *x; + t_methodentry *m, *mlist; + t_atomtype *wp, wanttype; + int i; + t_int ai[MAXPDARG+1], *ap = ai; + t_floatarg ad[MAXPDARG+1], *dp = ad; + int narg = 0; + t_pd *bonzo; + + /* check for messages that are handled by fixed slots in the class + structure. We don't catch "pointer" though so that sending "pointer" + to pd_objectmaker doesn't require that we supply a pointer value. */ + if (s == &s_float) + { + if (!argc) (*c->c_floatmethod)(x, 0.); + else if (argv->a_type == A_FLOAT) + (*c->c_floatmethod)(x, argv->a_w.w_float); + else goto badarg; + return; + } + if (s == &s_bang) + { + (*c->c_bangmethod)(x); + return; + } + if (s == &s_list) + { + (*c->c_listmethod)(x, s, argc, argv); + return; + } + if (s == &s_symbol) + { + if (argc && argv->a_type == A_SYMBOL) + (*c->c_symbolmethod)(x, argv->a_w.w_symbol); + else + (*c->c_symbolmethod)(x, &s_); + return; + } +#ifdef PDINSTANCE + mlist = c->c_methods[pd_this->pd_instanceno]; +#else + mlist = c->c_methods; +#endif + for (i = c->c_nmethod, m = mlist; i--; m++) + if (m->me_name == s) + { + wp = m->me_arg; + if (*wp == A_GIMME) + { + if (x == &pd_objectmaker) + pd_this->pd_newest = + (*((t_newgimme)(m->me_fun)))(s, argc, argv); + else (*((t_messgimme)(m->me_fun)))(x, s, argc, argv); + return; + } + if (argc > MAXPDARG) argc = MAXPDARG; + if (x != &pd_objectmaker) *(ap++) = (t_int)x, narg++; + while ((wanttype = *wp++)) + { + switch (wanttype) + { + case A_POINTER: + if (!argc) goto badarg; + else + { + if (argv->a_type == A_POINTER) + *ap = (t_int)(argv->a_w.w_gpointer); + else goto badarg; + argc--; + argv++; + } + narg++; + ap++; + break; + case A_FLOAT: + if (!argc) goto badarg; /* falls through */ + case A_DEFFLOAT: + if (!argc) *dp = 0; + else + { + if (argv->a_type == A_FLOAT) + *dp = argv->a_w.w_float; + else goto badarg; + argc--; + argv++; + } + dp++; + break; + case A_SYMBOL: + if (!argc) goto badarg; /* falls through */ + case A_DEFSYM: + if (!argc) *ap = (t_int)(&s_); + else + { + if (argv->a_type == A_SYMBOL) + *ap = (t_int)(argv->a_w.w_symbol); + /* if it's an unfilled "dollar" argument it appears + as zero here; cheat and bash it to the null + symbol. Unfortunately, this lets real zeros + pass as symbols too, which seems wrong... */ + else if (x == &pd_objectmaker && argv->a_type == A_FLOAT + && argv->a_w.w_float == 0) + *ap = (t_int)(&s_); + else goto badarg; + argc--; + argv++; + } + narg++; + ap++; + break; + default: + goto badarg; + } + } + switch (narg) + { + case 0 : bonzo = (*(t_fun0)(m->me_fun)) + (ad[0], ad[1], ad[2], ad[3], ad[4]); break; + case 1 : bonzo = (*(t_fun1)(m->me_fun)) + (ai[0], ad[0], ad[1], ad[2], ad[3], ad[4]); break; + case 2 : bonzo = (*(t_fun2)(m->me_fun)) + (ai[0], ai[1], ad[0], ad[1], ad[2], ad[3], ad[4]); break; + case 3 : bonzo = (*(t_fun3)(m->me_fun)) + (ai[0], ai[1], ai[2], ad[0], ad[1], ad[2], ad[3], ad[4]); break; + case 4 : bonzo = (*(t_fun4)(m->me_fun)) + (ai[0], ai[1], ai[2], ai[3], + ad[0], ad[1], ad[2], ad[3], ad[4]); break; + case 5 : bonzo = (*(t_fun5)(m->me_fun)) + (ai[0], ai[1], ai[2], ai[3], ai[4], + ad[0], ad[1], ad[2], ad[3], ad[4]); break; + case 6 : bonzo = (*(t_fun6)(m->me_fun)) + (ai[0], ai[1], ai[2], ai[3], ai[4], ai[5], + ad[0], ad[1], ad[2], ad[3], ad[4]); break; + default: bonzo = 0; + } + if (x == &pd_objectmaker) + pd_this->pd_newest = bonzo; + return; + } + (*c->c_anymethod)(x, s, argc, argv); + return; +badarg: + pd_error(x, "Bad arguments for message '%s' to object '%s'", + s->s_name, c->c_name->s_name); +} + + /* convenience routine giving a stdarg interface to typedmess(). Only + ten args supported; it seems unlikely anyone will need more since + longer messages are likely to be programmatically generated anyway. */ +void pd_vmess(t_pd *x, t_symbol *sel, char *fmt, ...) +{ + va_list ap; + t_atom arg[10], *at = arg; + int nargs = 0; + char *fp = fmt; + + va_start(ap, fmt); + while (1) + { + if (nargs >= 10) + { + pd_error(x, "pd_vmess: only 10 allowed"); + break; + } + switch(*fp++) + { + case 'f': SETFLOAT(at, va_arg(ap, double)); break; + case 's': SETSYMBOL(at, va_arg(ap, t_symbol *)); break; + case 'i': SETFLOAT(at, va_arg(ap, t_int)); break; + case 'p': SETPOINTER(at, va_arg(ap, t_gpointer *)); break; + default: goto done; + } + at++; + nargs++; + } +done: + va_end(ap); + typedmess(x, sel, nargs, arg); +} + +void pd_forwardmess(t_pd *x, int argc, t_atom *argv) +{ + if (argc) + { + t_atomtype t = argv->a_type; + if (t == A_SYMBOL) pd_typedmess(x, argv->a_w.w_symbol, argc-1, argv+1); + else if (t == A_POINTER) + { + if (argc == 1) pd_pointer(x, argv->a_w.w_gpointer); + else pd_list(x, &s_list, argc, argv); + } + else if (t == A_FLOAT) + { + if (argc == 1) pd_float(x, argv->a_w.w_float); + else pd_list(x, &s_list, argc, argv); + } + else bug("pd_forwardmess"); + } + +} + +void nullfn(void) {} + +t_gotfn getfn(t_pd *x, t_symbol *s) +{ + t_class *c = *x; + t_methodentry *m, *mlist; + int i; + +#ifdef PDINSTANCE + mlist = c->c_methods[pd_this->pd_instanceno]; +#else + mlist = c->c_methods; +#endif + for (i = c->c_nmethod, m = mlist; i--; m++) + if (m->me_name == s) return(m->me_fun); + pd_error(x, "%s: no method for message '%s'", c->c_name->s_name, s->s_name); + return((t_gotfn)nullfn); +} + +t_gotfn zgetfn(t_pd *x, t_symbol *s) +{ + t_class *c = *x; + t_methodentry *m, *mlist; + int i; + +#ifdef PDINSTANCE + mlist = c->c_methods[pd_this->pd_instanceno]; +#else + mlist = c->c_methods; +#endif + for (i = c->c_nmethod, m = mlist; i--; m++) + if (m->me_name == s) return(m->me_fun); + return(0); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/m_conf.c b/ports/camomile/source/LibPd/pure-data/src/m_conf.c new file mode 100644 index 00000000..5932e288 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/m_conf.c @@ -0,0 +1,110 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* changes by Thomas Musil IEM KUG Graz Austria 2001 */ +/* all changes are labeled with iemlib */ + +#include "m_pd.h" + +void g_array_setup(void); +void g_canvas_setup(void); +void g_guiconnect_setup(void); +/* iemlib */ +void g_bang_setup(void); +void g_hradio_setup(void); +void g_hslider_setup(void); +void g_mycanvas_setup(void); +void g_numbox_setup(void); +void g_toggle_setup(void); +void g_vradio_setup(void); +void g_vslider_setup(void); +void g_vumeter_setup(void); +/* iemlib */ +void g_io_setup(void); +void g_scalar_setup(void); +void g_template_setup(void); +void g_text_setup(void); +void g_traversal_setup(void); +void clone_setup(void); +void m_pd_setup(void); +void x_acoustics_setup(void); +void x_interface_setup(void); +void x_connective_setup(void); +void x_time_setup(void); +void x_arithmetic_setup(void); +void x_array_setup(void); +void x_midi_setup(void); +void x_misc_setup(void); +void x_net_setup(void); +void x_qlist_setup(void); +void x_gui_setup(void); +void x_list_setup(void); +void x_scalar_setup(void); +void expr_setup(void); +void d_arithmetic_setup(void); +void d_array_setup(void); +void d_ctl_setup(void); +void d_dac_setup(void); +void d_delay_setup(void); +void d_fft_setup(void); +void d_filter_setup(void); +void d_global_setup(void); +void d_math_setup(void); +void d_misc_setup(void); +void d_osc_setup(void); +void d_soundfile_setup(void); +void d_ugen_setup(void); + +void conf_init(void) +{ + g_array_setup(); + g_canvas_setup(); + g_guiconnect_setup(); +/* iemlib */ + g_bang_setup(); + g_hradio_setup(); + g_hslider_setup(); + g_mycanvas_setup(); + g_numbox_setup(); + g_toggle_setup(); + g_vradio_setup(); + g_vslider_setup(); + g_vumeter_setup(); +/* iemlib */ + g_io_setup(); + g_scalar_setup(); + g_template_setup(); + g_text_setup(); + g_traversal_setup(); + clone_setup(); + m_pd_setup(); + x_acoustics_setup(); + x_interface_setup(); + x_connective_setup(); + x_time_setup(); + x_arithmetic_setup(); + x_array_setup(); + x_midi_setup(); + x_misc_setup(); + x_net_setup(); + x_qlist_setup(); + x_gui_setup(); + x_list_setup(); + x_scalar_setup(); + expr_setup(); + d_arithmetic_setup(); + d_array_setup(); + d_ctl_setup(); + d_dac_setup(); + d_delay_setup(); + d_fft_setup(); + d_filter_setup(); + d_global_setup(); + d_math_setup(); + d_misc_setup(); + d_osc_setup(); + d_soundfile_setup(); + d_ugen_setup(); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/m_glob.c b/ports/camomile/source/LibPd/pure-data/src/m_glob.c new file mode 100644 index 00000000..a30cc290 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/m_glob.c @@ -0,0 +1,216 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "m_imp.h" +#include "s_stuff.h" + +t_class *glob_pdobject; +static t_class *maxclass; + +int sys_perf; /* true if we should query user on close and quit */ +int pd_compatibilitylevel = 100000; /* e.g., 43 for pd 0.43 compatibility */ + +/* These "glob" routines, which implement messages to Pd, are from all +over. Some others are prototyped in m_imp.h as well. */ + +void glob_menunew(void *dummy, t_symbol *name, t_symbol *dir); +void glob_verifyquit(void *dummy, t_floatarg f); +void glob_dsp(void *dummy, t_symbol *s, int argc, t_atom *argv); +void glob_meters(void *dummy, t_floatarg f); +void glob_key(void *dummy, t_symbol *s, int ac, t_atom *av); +void glob_audiostatus(void *dummy); +void glob_finderror(t_pd *dummy); +void glob_findinstance(t_pd *dummy, t_symbol*s); +void glob_audio_properties(t_pd *dummy, t_floatarg flongform); +void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv); +void glob_audio_setapi(t_pd *dummy, t_floatarg f); +void glob_midi_properties(t_pd *dummy, t_floatarg flongform); +void glob_midi_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv); +void glob_midi_setapi(t_pd *dummy, t_floatarg f); +void glob_start_path_dialog(t_pd *dummy, t_floatarg flongform); +void glob_path_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv); +void glob_addtopath(t_pd *dummy, t_symbol *path, t_float saveit); +void glob_start_startup_dialog(t_pd *dummy, t_floatarg flongform); +void glob_startup_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv); +void glob_ping(t_pd *dummy); +void glob_plugindispatch(t_pd *dummy, t_symbol *s, int argc, t_atom *argv); +void glob_watchdog(t_pd *dummy); +void glob_loadpreferences(t_pd *dummy, t_symbol *s); +void glob_savepreferences(t_pd *dummy, t_symbol *s); +void glob_forgetpreferences(t_pd *dummy); + +static void glob_helpintro(t_pd *dummy) +{ + open_via_helppath("intro.pd", ""); +} + +static void glob_compatibility(t_pd *dummy, t_floatarg level) +{ + int dspwas = canvas_suspend_dsp(); + pd_compatibilitylevel = 0.5 + 100. * level; + canvas_resume_dsp(dspwas); +} + +#ifdef _WIN32 +void glob_audio(void *dummy, t_floatarg adc, t_floatarg dac); +#endif + +/* a method you add for debugging printout */ +void glob_foo(void *dummy, t_symbol *s, int argc, t_atom *argv); + +#if 0 +void glob_foo(void *dummy, t_symbol *s, int argc, t_atom *argv) +{ + post("foo 1"); + printf("barbarbar 2\n"); + post("foo 3"); +} +#endif + +static void glob_version(t_pd *dummy, float f) +{ + if (f > (PD_MAJOR_VERSION + 0.01*PD_MINOR_VERSION + 0.001)) + { + static int warned; + if (warned < 1) + post("warning: file format (%g) newer than this version (%g) of Pd", + f, PD_MAJOR_VERSION + 0.01*PD_MINOR_VERSION); + else if (warned < 2) + post("(... more file format messages suppressed)"); + warned++; + } +} + +static void glob_perf(t_pd *dummy, float f) +{ + sys_perf = (f != 0); +} + +void max_default(t_pd *x, t_symbol *s, int argc, t_atom *argv) +{ + int i; + char str[80]; + startpost("%s: unknown message %s ", class_getname(pd_class(x)), + s->s_name); + for (i = 0; i < argc; i++) + { + atom_string(argv+i, str, 80); + poststring(str); + } + endpost(); +} + +void glob_plugindispatch(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) +{ + int i; + char str[80]; + sys_vgui("pdtk_plugin_dispatch "); + for (i = 0; i < argc; i++) + { + atom_string(argv+i, str, 80); + sys_vgui("%s", str); + if (i < argc-1) { + sys_vgui(" "); + } + } + sys_vgui("\n"); +} + +int sys_zoom_open = 1; +void glob_zoom_open(t_pd *dummy, t_floatarg f) +{ + sys_zoom_open = (f != 0 ? 2 : 1); +} + +void glob_init(void) +{ + maxclass = class_new(gensym("max"), 0, 0, sizeof(t_pd), + CLASS_DEFAULT, A_NULL); + class_addanything(maxclass, max_default); + pd_bind(&maxclass, gensym("max")); + + glob_pdobject = class_new(gensym("pd"), 0, 0, sizeof(t_pd), + CLASS_DEFAULT, A_NULL); + class_addmethod(glob_pdobject, (t_method)glob_initfromgui, gensym("init"), + A_GIMME, 0); + class_addmethod(glob_pdobject, (t_method)glob_menunew, gensym("menunew"), + A_SYMBOL, A_SYMBOL, 0); + class_addmethod(glob_pdobject, (t_method)glob_evalfile, gensym("open"), + A_SYMBOL, A_SYMBOL, 0); + class_addmethod(glob_pdobject, (t_method)glob_quit, gensym("quit"), 0); + class_addmethod(glob_pdobject, (t_method)glob_verifyquit, + gensym("verifyquit"), A_DEFFLOAT, 0); + class_addmethod(glob_pdobject, (t_method)glob_foo, gensym("foo"), A_GIMME, 0); + class_addmethod(glob_pdobject, (t_method)glob_dsp, gensym("dsp"), A_GIMME, 0); + class_addmethod(glob_pdobject, (t_method)glob_meters, gensym("meters"), + A_FLOAT, 0); + class_addmethod(glob_pdobject, (t_method)glob_key, gensym("key"), A_GIMME, 0); + class_addmethod(glob_pdobject, (t_method)glob_audiostatus, + gensym("audiostatus"), 0); + class_addmethod(glob_pdobject, (t_method)glob_finderror, + gensym("finderror"), 0); + class_addmethod(glob_pdobject, (t_method)glob_findinstance, + gensym("findinstance"), A_SYMBOL, 0); + class_addmethod(glob_pdobject, (t_method)glob_audio_properties, + gensym("audio-properties"), A_DEFFLOAT, 0); + class_addmethod(glob_pdobject, (t_method)glob_audio_dialog, + gensym("audio-dialog"), A_GIMME, 0); + class_addmethod(glob_pdobject, (t_method)glob_audio_setapi, + gensym("audio-setapi"), A_FLOAT, 0); + class_addmethod(glob_pdobject, (t_method)glob_midi_setapi, + gensym("midi-setapi"), A_FLOAT, 0); + class_addmethod(glob_pdobject, (t_method)glob_midi_properties, + gensym("midi-properties"), A_DEFFLOAT, 0); + class_addmethod(glob_pdobject, (t_method)glob_midi_dialog, + gensym("midi-dialog"), A_GIMME, 0); + class_addmethod(glob_pdobject, (t_method)glob_start_path_dialog, + gensym("start-path-dialog"), 0); + class_addmethod(glob_pdobject, (t_method)glob_path_dialog, + gensym("path-dialog"), A_GIMME, 0); + class_addmethod(glob_pdobject, (t_method)glob_addtopath, + gensym("add-to-path"), A_SYMBOL, A_DEFFLOAT, 0); + class_addmethod(glob_pdobject, (t_method)glob_start_startup_dialog, + gensym("start-startup-dialog"), 0); + class_addmethod(glob_pdobject, (t_method)glob_startup_dialog, + gensym("startup-dialog"), A_GIMME, 0); + class_addmethod(glob_pdobject, (t_method)glob_ping, gensym("ping"), 0); + class_addmethod(glob_pdobject, (t_method)glob_loadpreferences, + gensym("load-preferences"), A_DEFSYM, 0); + class_addmethod(glob_pdobject, (t_method)glob_savepreferences, + gensym("save-preferences"), A_DEFSYM, 0); + class_addmethod(glob_pdobject, (t_method)glob_forgetpreferences, + gensym("forget-preferences"), A_DEFSYM, 0); + class_addmethod(glob_pdobject, (t_method)glob_zoom_open, + gensym("zoom-open"), A_FLOAT, 0); + class_addmethod(glob_pdobject, (t_method)glob_version, + gensym("version"), A_FLOAT, 0); + class_addmethod(glob_pdobject, (t_method)glob_perf, + gensym("perf"), A_FLOAT, 0); + class_addmethod(glob_pdobject, (t_method)glob_compatibility, + gensym("compatibility"), A_FLOAT, 0); + class_addmethod(glob_pdobject, (t_method)glob_plugindispatch, + gensym("plugin-dispatch"), A_GIMME, 0); + class_addmethod(glob_pdobject, (t_method)glob_helpintro, + gensym("help-intro"), A_GIMME, 0); +#if defined(__linux__) || defined(__FreeBSD_kernel__) + class_addmethod(glob_pdobject, (t_method)glob_watchdog, + gensym("watchdog"), 0); +#endif + class_addanything(glob_pdobject, max_default); + pd_bind(&glob_pdobject, gensym("pd")); +} + + /* function to return version number at run time. Any of the + calling pointers may be zero in case you don't need all of them. */ +void sys_getversion(int *major, int *minor, int *bugfix) +{ + if (major) + *major = PD_MAJOR_VERSION; + if (minor) + *minor = PD_MINOR_VERSION; + if (bugfix) + *bugfix = PD_BUGFIX_VERSION; +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/m_imp.h b/ports/camomile/source/LibPd/pure-data/src/m_imp.h new file mode 100644 index 00000000..a0a07687 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/m_imp.h @@ -0,0 +1,98 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This file contains function prototypes and data types used to implement +Pd, but not shared with Pd objects. */ + +/* NOTE: this file describes Pd implementation details which may change +in future releases. The public (stable) API is in m_pd.h. */ + +/* LATER consider whether to use 'char' for method arg types to save space */ +#ifndef __m_imp_h_ + +/* the structure for a method handler ala Max */ +typedef struct _methodentry +{ + t_symbol *me_name; + t_gotfn me_fun; + t_atomtype me_arg[MAXPDARG+1]; +} t_methodentry; + +EXTERN_STRUCT _widgetbehavior; + +typedef void (*t_bangmethod)(t_pd *x); +typedef void (*t_pointermethod)(t_pd *x, t_gpointer *gp); +typedef void (*t_floatmethod)(t_pd *x, t_float f); +typedef void (*t_symbolmethod)(t_pd *x, t_symbol *s); +typedef void (*t_listmethod)(t_pd *x, t_symbol *s, int argc, t_atom *argv); +typedef void (*t_anymethod)(t_pd *x, t_symbol *s, int argc, t_atom *argv); + +struct _class +{ + t_symbol *c_name; /* name (mostly for error reporting) */ + t_symbol *c_helpname; /* name of help file */ + t_symbol *c_externdir; /* directory extern was loaded from */ + size_t c_size; /* size of an instance */ +#ifdef PDINSTANCE + t_methodentry **c_methods; /* methods other than bang, etc below */ +#else + t_methodentry *c_methods; +#endif + int c_nmethod; /* number of methods */ + t_method c_freemethod; /* function to call before freeing */ + t_bangmethod c_bangmethod; /* common methods */ + t_pointermethod c_pointermethod; + t_floatmethod c_floatmethod; + t_symbolmethod c_symbolmethod; + t_listmethod c_listmethod; + t_anymethod c_anymethod; + const struct _widgetbehavior *c_wb; /* "gobjs" only */ + const struct _parentwidgetbehavior *c_pwb;/* widget behavior in parent */ + t_savefn c_savefn; /* function to call when saving */ + t_propertiesfn c_propertiesfn; /* function to start prop dialog */ + struct _class *c_next; + int c_floatsignalin; /* onset to float for signal input */ + char c_gobj; /* true if is a gobj */ + char c_patchable; /* true if we have a t_object header */ + char c_firstin; /* if patchable, true if draw first inlet */ + char c_drawcommand; /* a drawing command for a template */ +}; + +/* m_class.c */ +EXTERN void pd_emptylist(t_pd *x); + +/* m_obj.c */ +EXTERN int obj_noutlets(t_object *x); +EXTERN int obj_ninlets(t_object *x); +EXTERN t_outconnect *obj_starttraverseoutlet(t_object *x, t_outlet **op, + int nout); +EXTERN t_outconnect *obj_nexttraverseoutlet(t_outconnect *lastconnect, + t_object **destp, t_inlet **inletp, int *whichp); +EXTERN t_outconnect *obj_connect(t_object *source, int outno, + t_object *sink, int inno); +EXTERN void obj_disconnect(t_object *source, int outno, t_object *sink, + int inno); +EXTERN void outlet_setstacklim(void); +EXTERN int obj_issignalinlet(t_object *x, int m); +EXTERN int obj_issignaloutlet(t_object *x, int m); +EXTERN int obj_nsiginlets(t_object *x); +EXTERN int obj_nsigoutlets(t_object *x); +EXTERN int obj_siginletindex(t_object *x, int m); +EXTERN int obj_sigoutletindex(t_object *x, int m); + +/* s_inter.c */ +void pd_globallock( void); +void pd_globalunlock( void); + +/* misc */ +#define SYMTABHASHSIZE 1024 + +EXTERN t_pd *glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir); +EXTERN void glob_initfromgui(void *dummy, t_symbol *s, int argc, t_atom *argv); +EXTERN void glob_quit(void *dummy); +EXTERN void open_via_helppath(const char *name, const char *dir); + + +#define __m_imp_h_ +#endif /* __m_imp_h_ */ diff --git a/ports/camomile/source/LibPd/pure-data/src/m_memory.c b/ports/camomile/source/LibPd/pure-data/src/m_memory.c new file mode 100644 index 00000000..f598e4f8 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/m_memory.c @@ -0,0 +1,89 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include +#include +#include "m_pd.h" +#include "m_imp.h" + +/* #define LOUD */ +#ifdef LOUD +#include +#endif + +/* #define DEBUGMEM */ +#ifdef DEBUGMEM +static int totalmem = 0; +#endif + +void *getbytes(size_t nbytes) +{ + void *ret; + if (nbytes < 1) nbytes = 1; + ret = (void *)calloc(nbytes, 1); +#ifdef LOUD + fprintf(stderr, "new %lx %d\n", (int)ret, nbytes); +#endif /* LOUD */ +#ifdef DEBUGMEM + totalmem += nbytes; +#endif + if (!ret) + post("pd: getbytes() failed -- out of memory"); + return (ret); +} + +void *getzbytes(size_t nbytes) /* obsolete name */ +{ + return (getbytes(nbytes)); +} + +void *copybytes(void *src, size_t nbytes) +{ + void *ret; + ret = getbytes(nbytes); + if (nbytes) + memcpy(ret, src, nbytes); + return (ret); +} + +void *resizebytes(void *old, size_t oldsize, size_t newsize) +{ + void *ret; + if (newsize < 1) newsize = 1; + if (oldsize < 1) oldsize = 1; + ret = (void *)realloc((char *)old, newsize); + if (newsize > oldsize && ret) + memset(((char *)ret) + oldsize, 0, newsize - oldsize); +#ifdef LOUD + fprintf(stderr, "resize %lx %d --> %lx %d\n", (int)old, oldsize, (int)ret, newsize); +#endif /* LOUD */ +#ifdef DEBUGMEM + totalmem += (newsize - oldsize); +#endif + if (!ret) + post("pd: resizebytes() failed -- out of memory"); + return (ret); +} + +void freebytes(void *fatso, size_t nbytes) +{ + if (nbytes == 0) + nbytes = 1; +#ifdef LOUD + fprintf(stderr, "free %lx %d\n", (int)fatso, nbytes); +#endif /* LOUD */ +#ifdef DEBUGMEM + totalmem -= nbytes; +#endif + free(fatso); +} + +#ifdef DEBUGMEM +#include + +void glob_foo(void *dummy, t_symbol *s, int argc, t_atom *argv) +{ + fprintf(stderr, "total mem %d\n", totalmem); +} +#endif diff --git a/ports/camomile/source/LibPd/pure-data/src/m_obj.c b/ports/camomile/source/LibPd/pure-data/src/m_obj.c new file mode 100644 index 00000000..4486858f --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/m_obj.c @@ -0,0 +1,756 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* this file handles Max-style patchable objects, i.e., objects which +can interconnect via inlets and outlets; also, the (terse) generic +behavior for "gobjs" appears at the end of this file. */ + +#include "m_pd.h" +#include "m_imp.h" + +union inletunion +{ + t_symbol *iu_symto; + t_gpointer *iu_pointerslot; + t_float *iu_floatslot; + t_symbol **iu_symslot; + t_float iu_floatsignalvalue; +}; + +struct _inlet +{ + t_pd i_pd; + struct _inlet *i_next; + t_object *i_owner; + t_pd *i_dest; + t_symbol *i_symfrom; + union inletunion i_un; +}; + +#define i_symto i_un.iu_symto +#define i_pointerslot i_un.iu_pointerslot +#define i_floatslot i_un.iu_floatslot +#define i_symslot i_un.iu_symslot + +static t_class *inlet_class, *pointerinlet_class, *floatinlet_class, + *symbolinlet_class; + +#define ISINLET(pd) ((*(pd) == inlet_class) || \ + (*(pd) == pointerinlet_class) || \ + (*(pd) == floatinlet_class) || \ + (*(pd) == symbolinlet_class)) + +/* --------------------- generic inlets ala max ------------------ */ + +t_inlet *inlet_new(t_object *owner, t_pd *dest, t_symbol *s1, t_symbol *s2) +{ + t_inlet *x = (t_inlet *)pd_new(inlet_class), *y, *y2; + x->i_owner = owner; + x->i_dest = dest; + if (s1 == &s_signal) + x->i_un.iu_floatsignalvalue = 0; + else x->i_symto = s2; + x->i_symfrom = s1; + x->i_next = 0; + if ((y = owner->ob_inlet)) + { + while ((y2 = y->i_next)) y = y2; + y->i_next = x; + } + else owner->ob_inlet = x; + return (x); +} + +t_inlet *signalinlet_new(t_object *owner, t_float f) +{ + t_inlet *x = inlet_new(owner, &owner->ob_pd, &s_signal, &s_signal); + x->i_un.iu_floatsignalvalue = f; + return (x); +} + +static void inlet_wrong(t_inlet *x, t_symbol *s) +{ + pd_error(x->i_owner, "inlet: expected '%s' but got '%s'", + x->i_symfrom->s_name, s->s_name); +} + +static void inlet_list(t_inlet *x, t_symbol *s, int argc, t_atom *argv); + + /* LATER figure out how to make these efficient: */ +static void inlet_bang(t_inlet *x) +{ + if (x->i_symfrom == &s_bang) + pd_vmess(x->i_dest, x->i_symto, ""); + else if (!x->i_symfrom) pd_bang(x->i_dest); + else if (x->i_symfrom == &s_list) + inlet_list(x, &s_bang, 0, 0); + else inlet_wrong(x, &s_bang); +} + +static void inlet_pointer(t_inlet *x, t_gpointer *gp) +{ + if (x->i_symfrom == &s_pointer) + pd_vmess(x->i_dest, x->i_symto, "p", gp); + else if (!x->i_symfrom) pd_pointer(x->i_dest, gp); + else if (x->i_symfrom == &s_list) + { + t_atom a; + SETPOINTER(&a, gp); + inlet_list(x, &s_pointer, 1, &a); + } + else inlet_wrong(x, &s_pointer); +} + +static void inlet_float(t_inlet *x, t_float f) +{ + if (x->i_symfrom == &s_float) + pd_vmess(x->i_dest, x->i_symto, "f", (t_floatarg)f); + else if (x->i_symfrom == &s_signal) + x->i_un.iu_floatsignalvalue = f; + else if (!x->i_symfrom) + pd_float(x->i_dest, f); + else if (x->i_symfrom == &s_list) + { + t_atom a; + SETFLOAT(&a, f); + inlet_list(x, &s_float, 1, &a); + } + else inlet_wrong(x, &s_float); +} + +static void inlet_symbol(t_inlet *x, t_symbol *s) +{ + if (x->i_symfrom == &s_symbol) + pd_vmess(x->i_dest, x->i_symto, "s", s); + else if (!x->i_symfrom) pd_symbol(x->i_dest, s); + else if (x->i_symfrom == &s_list) + { + t_atom a; + SETSYMBOL(&a, s); + inlet_list(x, &s_symbol, 1, &a); + } + else inlet_wrong(x, &s_symbol); +} + +static void inlet_list(t_inlet *x, t_symbol *s, int argc, t_atom *argv) +{ + t_atom at; + if (x->i_symfrom == &s_list || x->i_symfrom == &s_float + || x->i_symfrom == &s_symbol || x->i_symfrom == &s_pointer) + typedmess(x->i_dest, x->i_symto, argc, argv); + else if (!x->i_symfrom) pd_list(x->i_dest, s, argc, argv); + else if (!argc) + inlet_bang(x); + else if (argc==1 && argv->a_type == A_FLOAT) + inlet_float(x, atom_getfloat(argv)); + else if (argc==1 && argv->a_type == A_SYMBOL) + inlet_symbol(x, atom_getsymbol(argv)); + else inlet_wrong(x, &s_list); +} + +static void inlet_anything(t_inlet *x, t_symbol *s, int argc, t_atom *argv) +{ + if (x->i_symfrom == s) + typedmess(x->i_dest, x->i_symto, argc, argv); + else if (!x->i_symfrom) + typedmess(x->i_dest, s, argc, argv); + else inlet_wrong(x, s); +} + +void inlet_free(t_inlet *x) +{ + t_object *y = x->i_owner; + t_inlet *x2; + if (y->ob_inlet == x) y->ob_inlet = x->i_next; + else for (x2 = y->ob_inlet; x2; x2 = x2->i_next) + if (x2->i_next == x) + { + x2->i_next = x->i_next; + break; + } + t_freebytes(x, sizeof(*x)); +} + +/* ----- pointerinlets, floatinlets, syminlets: optimized inlets ------- */ + +static void pointerinlet_pointer(t_inlet *x, t_gpointer *gp) +{ + gpointer_unset(x->i_pointerslot); + *(x->i_pointerslot) = *gp; + if (gp->gp_stub) gp->gp_stub->gs_refcount++; +} + +t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp) +{ + t_inlet *x = (t_inlet *)pd_new(pointerinlet_class), *y, *y2; + x->i_owner = owner; + x->i_dest = 0; + x->i_symfrom = &s_pointer; + x->i_pointerslot = gp; + x->i_next = 0; + if ((y = owner->ob_inlet)) + { + while ((y2 = y->i_next)) y = y2; + y->i_next = x; + } + else owner->ob_inlet = x; + return (x); +} + +static void floatinlet_float(t_inlet *x, t_float f) +{ + *(x->i_floatslot) = f; +} + +t_inlet *floatinlet_new(t_object *owner, t_float *fp) +{ + t_inlet *x = (t_inlet *)pd_new(floatinlet_class), *y, *y2; + x->i_owner = owner; + x->i_dest = 0; + x->i_symfrom = &s_float; + x->i_floatslot = fp; + x->i_next = 0; + if ((y = owner->ob_inlet)) + { + while ((y2 = y->i_next)) y = y2; + y->i_next = x; + } + else owner->ob_inlet = x; + return (x); +} + +static void symbolinlet_symbol(t_inlet *x, t_symbol *s) +{ + *(x->i_symslot) = s; +} + +t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp) +{ + t_inlet *x = (t_inlet *)pd_new(symbolinlet_class), *y, *y2; + x->i_owner = owner; + x->i_dest = 0; + x->i_symfrom = &s_symbol; + x->i_symslot = sp; + x->i_next = 0; + if ((y = owner->ob_inlet)) + { + while ((y2 = y->i_next)) y = y2; + y->i_next = x; + } + else owner->ob_inlet = x; + return (x); +} + +/* ---------------------- routine to handle lists ---------------------- */ + + /* objects interpret lists by feeding them to the individual inlets. + Before you call this check that the object doesn't have a more + specific way to handle lists. */ +void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv) +{ + t_atom *ap; + int count; + t_inlet *ip = ((t_object *)x)->ob_inlet; + if (!argc) + { + pd_emptylist(&x->ob_pd); + return; + } + for (count = argc-1, ap = argv+1; ip && count--; ap++, ip = ip->i_next) + { + if (ap->a_type == A_POINTER) pd_pointer(&ip->i_pd, ap->a_w.w_gpointer); + else if (ap->a_type == A_FLOAT) pd_float(&ip->i_pd, ap->a_w.w_float); + else pd_symbol(&ip->i_pd, ap->a_w.w_symbol); + } + if (argv->a_type == A_POINTER) pd_pointer(&x->ob_pd, argv->a_w.w_gpointer); + else if (argv->a_type == A_FLOAT) pd_float(&x->ob_pd, argv->a_w.w_float); + else pd_symbol(&x->ob_pd, argv->a_w.w_symbol); +} + +void obj_init(void) +{ + inlet_class = class_new(gensym("inlet"), 0, 0, + sizeof(t_inlet), CLASS_PD, 0); + class_addbang(inlet_class, inlet_bang); + class_addpointer(inlet_class, inlet_pointer); + class_addfloat(inlet_class, inlet_float); + class_addsymbol(inlet_class, inlet_symbol); + class_addlist(inlet_class, inlet_list); + class_addanything(inlet_class, inlet_anything); + + pointerinlet_class = class_new(gensym("inlet"), 0, 0, + sizeof(t_inlet), CLASS_PD, 0); + class_addpointer(pointerinlet_class, pointerinlet_pointer); + class_addanything(pointerinlet_class, inlet_wrong); + + floatinlet_class = class_new(gensym("inlet"), 0, 0, + sizeof(t_inlet), CLASS_PD, 0); + class_addfloat(floatinlet_class, (t_method)floatinlet_float); + class_addanything(floatinlet_class, inlet_wrong); + + symbolinlet_class = class_new(gensym("inlet"), 0, 0, + sizeof(t_inlet), CLASS_PD, 0); + class_addsymbol(symbolinlet_class, symbolinlet_symbol); + class_addanything(symbolinlet_class, inlet_wrong); + +} + +/* --------------------------- outlets ------------------------------ */ + +static PERTHREAD int stackcount = 0; /* iteration counter */ +#define STACKITER 1000 /* maximum iterations allowed */ + +static PERTHREAD int outlet_eventno; + + /* set a stack limit (on each incoming event that can set off messages) + for the outlet functions to check to prevent stack overflow from message + recursion */ + +void outlet_setstacklim(void) +{ + outlet_eventno++; +} + + /* get a number unique to the (clock, MIDI, GUI, etc.) event we're on */ +int sched_geteventno( void) +{ + return (outlet_eventno); +} + +struct _outconnect +{ + struct _outconnect *oc_next; + t_pd *oc_to; +}; + +struct _outlet +{ + t_object *o_owner; + struct _outlet *o_next; + t_outconnect *o_connections; + t_symbol *o_sym; +}; + +t_outlet *outlet_new(t_object *owner, t_symbol *s) +{ + t_outlet *x = (t_outlet *)getbytes(sizeof(*x)), *y, *y2; + x->o_owner = owner; + x->o_next = 0; + if ((y = owner->ob_outlet)) + { + while ((y2 = y->o_next)) y = y2; + y->o_next = x; + } + else owner->ob_outlet = x; + x->o_connections = 0; + x->o_sym = s; + return (x); +} + +static void outlet_stackerror(t_outlet *x) +{ + pd_error(x->o_owner, "stack overflow"); +} + +void outlet_bang(t_outlet *x) +{ + t_outconnect *oc; + if(++stackcount >= STACKITER) + outlet_stackerror(x); + else + for (oc = x->o_connections; oc; oc = oc->oc_next) + pd_bang(oc->oc_to); + --stackcount; +} + +void outlet_pointer(t_outlet *x, t_gpointer *gp) +{ + t_outconnect *oc; + t_gpointer gpointer; + if(++stackcount >= STACKITER) + outlet_stackerror(x); + else + { + gpointer = *gp; + for (oc = x->o_connections; oc; oc = oc->oc_next) + pd_pointer(oc->oc_to, &gpointer); + } + --stackcount; +} + +void outlet_float(t_outlet *x, t_float f) +{ + t_outconnect *oc; + if(++stackcount >= STACKITER) + outlet_stackerror(x); + else + for (oc = x->o_connections; oc; oc = oc->oc_next) + pd_float(oc->oc_to, f); + --stackcount; +} + +void outlet_symbol(t_outlet *x, t_symbol *s) +{ + t_outconnect *oc; + if(++stackcount >= STACKITER) + outlet_stackerror(x); + else + for (oc = x->o_connections; oc; oc = oc->oc_next) + pd_symbol(oc->oc_to, s); + --stackcount; +} + +void outlet_list(t_outlet *x, t_symbol *s, int argc, t_atom *argv) +{ + t_outconnect *oc; + if(++stackcount >= STACKITER) + outlet_stackerror(x); + else + for (oc = x->o_connections; oc; oc = oc->oc_next) + pd_list(oc->oc_to, s, argc, argv); + --stackcount; +} + +void outlet_anything(t_outlet *x, t_symbol *s, int argc, t_atom *argv) +{ + t_outconnect *oc; + if(++stackcount >= STACKITER) + outlet_stackerror(x); + else + for (oc = x->o_connections; oc; oc = oc->oc_next) + typedmess(oc->oc_to, s, argc, argv); + --stackcount; +} + + /* get the outlet's declared symbol */ +t_symbol *outlet_getsymbol(t_outlet *x) +{ + return (x->o_sym); +} + +void outlet_free(t_outlet *x) +{ + t_object *y = x->o_owner; + t_outlet *x2; + if (y->ob_outlet == x) y->ob_outlet = x->o_next; + else for (x2 = y->ob_outlet; x2; x2 = x2->o_next) + if (x2->o_next == x) + { + x2->o_next = x->o_next; + break; + } + t_freebytes(x, sizeof(*x)); +} + + /* connect an outlet of one object to an inlet of another. The receiving + "pd" is usually a patchable object, but this may be used to add a + non-patchable pd to an outlet by specifying the 0th inlet. */ +t_outconnect *obj_connect(t_object *source, int outno, + t_object *sink, int inno) +{ + t_inlet *i; + t_outlet *o; + t_pd *to; + t_outconnect *oc, *oc2; + + for (o = source->ob_outlet; o && outno; o = o->o_next, outno--) ; + if (!o) return (0); + + if (sink->ob_pd->c_firstin) + { + if (!inno) + { + to = &sink->ob_pd; + goto doit; + } + else inno--; + } + for (i = sink->ob_inlet; i && inno; i = i->i_next, inno--) ; + if (!i) return (0); + to = &i->i_pd; +doit: + oc = (t_outconnect *)t_getbytes(sizeof(*oc)); + oc->oc_next = 0; + oc->oc_to = to; + /* append it to the end of the list */ + /* LATER we might cache the last "oc" to make this faster. */ + if ((oc2 = o->o_connections)) + { + while (oc2->oc_next) oc2 = oc2->oc_next; + oc2->oc_next = oc; + } + else o->o_connections = oc; + if (o->o_sym == &s_signal) canvas_update_dsp(); + + return (oc); +} + +void obj_disconnect(t_object *source, int outno, t_object *sink, int inno) +{ + t_inlet *i; + t_outlet *o; + t_pd *to; + t_outconnect *oc, *oc2; + + for (o = source->ob_outlet; o && outno; o = o->o_next, outno--) ; + if (!o) return; + if (sink->ob_pd->c_firstin) + { + if (!inno) + { + to = &sink->ob_pd; + goto doit; + } + else inno--; + } + for (i = sink->ob_inlet; i && inno; i = i->i_next, inno--) ; + if (!i) return; + to = &i->i_pd; +doit: + if (!(oc = o->o_connections)) return; + if (oc->oc_to == to) + { + o->o_connections = oc->oc_next; + freebytes(oc, sizeof(*oc)); + goto done; + } + while ((oc2 = oc->oc_next)) + { + if (oc2->oc_to == to) + { + oc->oc_next = oc2->oc_next; + freebytes(oc2, sizeof(*oc2)); + goto done; + } + oc = oc2; + } +done: + if (o->o_sym == &s_signal) canvas_update_dsp(); +} + +/* ------ traversal routines for code that can't see our structures ------ */ + +int obj_noutlets(t_object *x) +{ + int n; + t_outlet *o; + for (o = x->ob_outlet, n = 0; o; o = o->o_next) n++; + return (n); +} + +int obj_ninlets(t_object *x) +{ + int n; + t_inlet *i; + for (i = x->ob_inlet, n = 0; i; i = i->i_next) n++; + if (x->ob_pd->c_firstin) n++; + return (n); +} + +t_outconnect *obj_starttraverseoutlet(t_object *x, t_outlet **op, int nout) +{ + t_outlet *o = x->ob_outlet; + while (nout-- && o) o = o->o_next; + *op = o; + if (o) return (o->o_connections); + else return (0); +} + +t_outconnect *obj_nexttraverseoutlet(t_outconnect *lastconnect, + t_object **destp, t_inlet **inletp, int *whichp) +{ + t_pd *y; + y = lastconnect->oc_to; + if (ISINLET(y)) + { + int n; + t_inlet *i = (t_inlet *)y, *i2; + t_object *dest = i->i_owner; + for (n = dest->ob_pd->c_firstin, i2 = dest->ob_inlet; + i2 && i2 != i; i2 = i2->i_next) n++; + *whichp = n; + *destp = dest; + *inletp = i; + } + else + { + *whichp = 0; + *inletp = 0; + *destp = ((t_object *)y); + } + return (lastconnect->oc_next); +} + + /* this one checks that a pd is indeed a patchable object, and returns + it, correctly typed, or zero if the check failed. */ +t_object *pd_checkobject(t_pd *x) +{ + if ((*x)->c_patchable) return ((t_object *)x); + else return (0); +} + + /* move an inlet or outlet to the head of the list */ +void obj_moveinletfirst(t_object *x, t_inlet *i) +{ + t_inlet *i2; + if (x->ob_inlet == i) return; + else for (i2 = x->ob_inlet; i2; i2 = i2->i_next) + if (i2->i_next == i) + { + i2->i_next = i->i_next; + i->i_next = x->ob_inlet; + x->ob_inlet = i; + return; + } +} + +void obj_moveoutletfirst(t_object *x, t_outlet *o) +{ + t_outlet *o2; + if (x->ob_outlet == o) return; + else for (o2 = x->ob_outlet; o2; o2 = o2->o_next) + if (o2->o_next == o) + { + o2->o_next = o->o_next; + o->o_next = x->ob_outlet; + x->ob_outlet = o; + return; + } +} + + /* routines for DSP sorting, which are used in d_ugen.c and g_canvas.c */ + /* LATER try to consolidate all the slightly different routines. */ + +int obj_nsiginlets(t_object *x) +{ + int n; + t_inlet *i; + for (i = x->ob_inlet, n = 0; i; i = i->i_next) + if (i->i_symfrom == &s_signal) n++; + if (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin) n++; + return (n); +} + + /* get the index, among signal inlets, of the mth inlet overall */ +int obj_siginletindex(t_object *x, int m) +{ + int n = 0; + t_inlet *i; + if (x->ob_pd->c_firstin) + { + if (!m--) + return (0); + if (x->ob_pd->c_floatsignalin) + n++; + } + for (i = x->ob_inlet; i; i = i->i_next, m--) + if (i->i_symfrom == &s_signal) + { + if (m == 0) return (n); + n++; + } + return (-1); +} + +int obj_issignalinlet(t_object *x, int m) +{ + t_inlet *i; + if (x->ob_pd->c_firstin) + { + if (!m) + return (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin); + else m--; + } + for (i = x->ob_inlet; i && m; i = i->i_next, m--) + ; + return (i && (i->i_symfrom == &s_signal)); +} + +int obj_nsigoutlets(t_object *x) +{ + int n; + t_outlet *o; + for (o = x->ob_outlet, n = 0; o; o = o->o_next) + if (o->o_sym == &s_signal) n++; + return (n); +} + +int obj_sigoutletindex(t_object *x, int m) +{ + int n; + t_outlet *o2; + for (o2 = x->ob_outlet, n = 0; o2; o2 = o2->o_next, m--) + if (o2->o_sym == &s_signal) + { + if (m == 0) return (n); + n++; + } + return (-1); +} + +int obj_issignaloutlet(t_object *x, int m) +{ + int n; + t_outlet *o2; + for (o2 = x->ob_outlet, n = 0; o2 && m--; o2 = o2->o_next); + return (o2 && (o2->o_sym == &s_signal)); +} + +t_float *obj_findsignalscalar(t_object *x, int m) +{ + t_inlet *i; + if (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin) + { + if (!m--) + return (x->ob_pd->c_floatsignalin > 0 ? + (t_float *)(((char *)x) + x->ob_pd->c_floatsignalin) : 0); + } + for (i = x->ob_inlet; i; i = i->i_next) + if (i->i_symfrom == &s_signal) + { + if (m-- == 0) + return (&i->i_un.iu_floatsignalvalue); + } + return (0); +} + +/* and these are only used in g_io.c... */ + +int inlet_getsignalindex(t_inlet *x) +{ + int n = 0; + t_inlet *i; + if (x->i_symfrom != &s_signal) + bug("inlet_getsignalindex"); + for (i = x->i_owner->ob_inlet, n = 0; i && i != x; i = i->i_next) + if (i->i_symfrom == &s_signal) n++; + return (n); +} + +int outlet_getsignalindex(t_outlet *x) +{ + int n = 0; + t_outlet *o; + for (o = x->o_owner->ob_outlet, n = 0; o && o != x; o = o->o_next) + if (o->o_sym == &s_signal) n++; + return (n); +} + +void obj_saveformat(t_object *x, t_binbuf *bb) +{ + if (x->te_width) + binbuf_addv(bb, "ssf;", &s__X, gensym("f"), (float)x->te_width); +} + +/* this one only in g_clone.c -- LATER consider sending the message +without having to chase the linked list every time? */ +void obj_sendinlet(t_object *x, int n, t_symbol *s, int argc, t_atom *argv) +{ + t_inlet *i; + for (i = x->ob_inlet; i && n; i = i->i_next, n--) + ; + if (i) + typedmess(&i->i_pd, s, argc, argv); + else bug("obj_sendinlet"); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/m_pd.c b/ports/camomile/source/LibPd/pure-data/src/m_pd.c new file mode 100644 index 00000000..ce57ef52 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/m_pd.c @@ -0,0 +1,321 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include +#include +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" /* just for LB_LOAD */ + + /* FIXME no out-of-memory testing yet! */ + +t_pd *pd_new(t_class *c) +{ + t_pd *x; + if (!c) + bug ("pd_new: apparently called before setup routine"); + x = (t_pd *)t_getbytes(c->c_size); + *x = c; + if (c->c_patchable) + { + ((t_object *)x)->ob_inlet = 0; + ((t_object *)x)->ob_outlet = 0; + } + return (x); +} + +void pd_free(t_pd *x) +{ + t_class *c = *x; + if (c->c_freemethod) (*(t_gotfn)(c->c_freemethod))(x); + if (c->c_patchable) + { + while (((t_object *)x)->ob_outlet) + outlet_free(((t_object *)x)->ob_outlet); + while (((t_object *)x)->ob_inlet) + inlet_free(((t_object *)x)->ob_inlet); + if (((t_object *)x)->ob_binbuf) + binbuf_free(((t_object *)x)->ob_binbuf); + } + if (c->c_size) t_freebytes(x, c->c_size); +} + +void gobj_save(t_gobj *x, t_binbuf *b) +{ + t_class *c = x->g_pd; + if (c->c_savefn) + (c->c_savefn)(x, b); +} + +/* deal with several objects bound to the same symbol. If more than one, we +actually bind a collection object to the symbol, which forwards messages sent +to the symbol. */ + +static t_class *bindlist_class; + +typedef struct _bindelem +{ + t_pd *e_who; + struct _bindelem *e_next; +} t_bindelem; + +typedef struct _bindlist +{ + t_pd b_pd; + t_bindelem *b_list; +} t_bindlist; + +static void bindlist_bang(t_bindlist *x) +{ + t_bindelem *e; + for (e = x->b_list; e; e = e->e_next) + pd_bang(e->e_who); +} + +static void bindlist_float(t_bindlist *x, t_float f) +{ + t_bindelem *e; + for (e = x->b_list; e; e = e->e_next) + pd_float(e->e_who, f); +} + +static void bindlist_symbol(t_bindlist *x, t_symbol *s) +{ + t_bindelem *e; + for (e = x->b_list; e; e = e->e_next) + pd_symbol(e->e_who, s); +} + +static void bindlist_pointer(t_bindlist *x, t_gpointer *gp) +{ + t_bindelem *e; + for (e = x->b_list; e; e = e->e_next) + pd_pointer(e->e_who, gp); +} + +static void bindlist_list(t_bindlist *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_bindelem *e; + for (e = x->b_list; e; e = e->e_next) + pd_list(e->e_who, s, argc, argv); +} + +static void bindlist_anything(t_bindlist *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_bindelem *e; + for (e = x->b_list; e; e = e->e_next) + pd_typedmess(e->e_who, s, argc, argv); +} + +void m_pd_setup(void) +{ + bindlist_class = class_new(gensym("bindlist"), 0, 0, + sizeof(t_bindlist), CLASS_PD, 0); + class_addbang(bindlist_class, bindlist_bang); + class_addfloat(bindlist_class, (t_method)bindlist_float); + class_addsymbol(bindlist_class, bindlist_symbol); + class_addpointer(bindlist_class, bindlist_pointer); + class_addlist(bindlist_class, bindlist_list); + class_addanything(bindlist_class, bindlist_anything); +} + +void pd_bind(t_pd *x, t_symbol *s) +{ + if (s->s_thing) + { + if (*s->s_thing == bindlist_class) + { + t_bindlist *b = (t_bindlist *)s->s_thing; + t_bindelem *e = (t_bindelem *)getbytes(sizeof(t_bindelem)); + e->e_next = b->b_list; + e->e_who = x; + b->b_list = e; + } + else + { + t_bindlist *b = (t_bindlist *)pd_new(bindlist_class); + t_bindelem *e1 = (t_bindelem *)getbytes(sizeof(t_bindelem)); + t_bindelem *e2 = (t_bindelem *)getbytes(sizeof(t_bindelem)); + b->b_list = e1; + e1->e_who = x; + e1->e_next = e2; + e2->e_who = s->s_thing; + e2->e_next = 0; + s->s_thing = &b->b_pd; + } + } + else s->s_thing = x; +} + +void pd_unbind(t_pd *x, t_symbol *s) +{ + if (s->s_thing == x) s->s_thing = 0; + else if (s->s_thing && *s->s_thing == bindlist_class) + { + /* bindlists always have at least two elements... if the number + goes down to one, get rid of the bindlist and bind the symbol + straight to the remaining element. */ + + t_bindlist *b = (t_bindlist *)s->s_thing; + t_bindelem *e, *e2; + if ((e = b->b_list)->e_who == x) + { + b->b_list = e->e_next; + freebytes(e, sizeof(t_bindelem)); + } + else for (e = b->b_list; (e2 = e->e_next); e = e2) + if (e2->e_who == x) + { + e->e_next = e2->e_next; + freebytes(e2, sizeof(t_bindelem)); + break; + } + if (!b->b_list->e_next) + { + s->s_thing = b->b_list->e_who; + freebytes(b->b_list, sizeof(t_bindelem)); + pd_free(&b->b_pd); + } + } + else pd_error(x, "%s: couldn't unbind", s->s_name); +} + +t_pd *pd_findbyclass(t_symbol *s, t_class *c) +{ + t_pd *x = 0; + + if (!s->s_thing) return (0); + if (*s->s_thing == c) return (s->s_thing); + if (*s->s_thing == bindlist_class) + { + t_bindlist *b = (t_bindlist *)s->s_thing; + t_bindelem *e, *e2; + int warned = 0; + for (e = b->b_list; e; e = e->e_next) + if (*e->e_who == c) + { + if (x && !warned) + { + post("warning: %s: multiply defined", s->s_name); + warned = 1; + } + x = e->e_who; + } + } + return x; +} + +/* stack for maintaining bindings for the #X symbol during nestable loads. +*/ + +typedef struct _gstack +{ + t_pd *g_what; + t_symbol *g_loadingabstraction; + struct _gstack *g_next; +} t_gstack; + +static t_gstack *gstack_head = 0; +static t_pd *lastpopped; +static t_symbol *pd_loadingabstraction; + +int pd_setloadingabstraction(t_symbol *sym) +{ + t_gstack *foo = gstack_head; + for (foo = gstack_head; foo; foo = foo->g_next) + if (foo->g_loadingabstraction == sym) + return (1); + pd_loadingabstraction = sym; + return (0); +} + +void pd_pushsym(t_pd *x) +{ + t_gstack *y = (t_gstack *)t_getbytes(sizeof(*y)); + y->g_what = s__X.s_thing; + y->g_next = gstack_head; + y->g_loadingabstraction = pd_loadingabstraction; + pd_loadingabstraction = 0; + gstack_head = y; + s__X.s_thing = x; +} + +void pd_popsym(t_pd *x) +{ + if (!gstack_head || s__X.s_thing != x) bug("gstack_pop"); + else + { + t_gstack *headwas = gstack_head; + s__X.s_thing = headwas->g_what; + gstack_head = headwas->g_next; + t_freebytes(headwas, sizeof(*headwas)); + lastpopped = x; + } +} + +void pd_doloadbang( void) +{ + if (lastpopped) + pd_vmess(lastpopped, gensym("loadbang"), "f", LB_LOAD); + lastpopped = 0; +} + +void pd_bang(t_pd *x) +{ + (*(*x)->c_bangmethod)(x); +} + +void pd_float(t_pd *x, t_float f) +{ + (*(*x)->c_floatmethod)(x, f); +} + +void pd_pointer(t_pd *x, t_gpointer *gp) +{ + (*(*x)->c_pointermethod)(x, gp); +} + +void pd_symbol(t_pd *x, t_symbol *s) +{ + (*(*x)->c_symbolmethod)(x, s); +} + +void pd_list(t_pd *x, t_symbol *s, int argc, t_atom *argv) +{ + (*(*x)->c_listmethod)(x, &s_list, argc, argv); +} + +void mess_init(void); +void obj_init(void); +void conf_init(void); +void glob_init(void); +void garray_init(void); + +void pd_init(void) +{ + static int initted = 0; + if (initted) + return; + initted = 1; +#ifdef PDINSTANCE + pd_instances = (t_pdinstance **)getbytes(sizeof(*pd_instances)); + pd_instances[0] = &pd_maininstance; + pd_ninstances = 1; +#endif + mess_init(); + sys_lock(); + obj_init(); + conf_init(); + glob_init(); + garray_init(); + sys_unlock(); +} + +EXTERN t_canvas *pd_getcanvaslist(void) +{ + return (pd_this->pd_canvaslist); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/m_pd.h b/ports/camomile/source/LibPd/pure-data/src/m_pd.h new file mode 100644 index 00000000..fc31caff --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/m_pd.h @@ -0,0 +1,894 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __m_pd_h_ + +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) +extern "C" { +#endif + +#define PD_MAJOR_VERSION 0 +#define PD_MINOR_VERSION 48 +#define PD_BUGFIX_VERSION 1 +#define PD_TEST_VERSION "" +extern int pd_compatibilitylevel; /* e.g., 43 for pd 0.43 compatibility */ + +/* old name for "MSW" flag -- we have to take it for the sake of many old +"nmakefiles" for externs, which will define NT and not MSW */ +#if defined(NT) && !defined(MSW) +#define MSW +#endif + +/* These pragmas are only used for MSVC, not MinGW or Cygwin */ +#ifdef _MSC_VER +/* #pragma warning( disable : 4091 ) */ +#pragma warning( disable : 4305 ) /* uncast const double to float */ +#pragma warning( disable : 4244 ) /* uncast float/int conversion etc. */ +#pragma warning( disable : 4101 ) /* unused automatic variables */ +#endif /* _MSC_VER */ + + /* the external storage class is "extern" in UNIX; in MSW it's ugly. */ +#ifdef _WIN32 +#ifdef PD_INTERNAL +#define EXTERN __declspec(dllexport) extern +#else +#define EXTERN __declspec(dllimport) extern +#endif /* PD_INTERNAL */ +#else +#define EXTERN extern +#endif /* _WIN32 */ + + /* On most c compilers, you can just say "struct foo;" to declare a + structure whose elements are defined elsewhere. On MSVC, when compiling + C (but not C++) code, you have to say "extern struct foo;". So we make + a stupid macro: */ +#if defined(_MSC_VER) && !defined(_LANGUAGE_C_PLUS_PLUS) \ + && !defined(__cplusplus) +#define EXTERN_STRUCT extern struct +#else +#define EXTERN_STRUCT struct +#endif + +/* Define some attributes, specific to the compiler */ +#if defined(__GNUC__) +#define ATTRIBUTE_FORMAT_PRINTF(a, b) __attribute__ ((format (printf, a, b))) +#else +#define ATTRIBUTE_FORMAT_PRINTF(a, b) +#endif + +#if !defined(_SIZE_T) && !defined(_SIZE_T_) +#include /* just for size_t -- how lame! */ +#endif + +/* Microsoft Visual Studio is not C99, it does not provide stdint.h */ +#ifdef _MSC_VER +typedef signed __int8 int8_t; +typedef signed __int16 int16_t; +typedef signed __int32 int32_t; +typedef signed __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#else +# include +#endif + +/* for FILE, needed by sys_fopen() and sys_fclose() only */ +#include + +#define MAXPDSTRING 1000 /* use this for anything you want */ +#define MAXPDARG 5 /* max number of args we can typecheck today */ + +/* signed and unsigned integer types the size of a pointer: */ +#if !defined(PD_LONGINTTYPE) +#if defined(_WIN32) && defined(__x86_64__) +#define PD_LONGINTTYPE long long +#else +#define PD_LONGINTTYPE long +#endif +#endif + +#if !defined(PD_FLOATSIZE) + /* normally, our floats (t_float, t_sample,...) are 32bit */ +# define PD_FLOATSIZE 32 +#endif + +#if PD_FLOATSIZE == 32 +# define PD_FLOATTYPE float +/* an unsigned int of the same size as FLOATTYPE: */ +# define PD_FLOATUINTTYPE unsigned int + +#elif PD_FLOATSIZE == 64 +# define PD_FLOATTYPE double +# define PD_FLOATUINTTYPE unsigned long +#else +# error invalid FLOATSIZE: must be 32 or 64 +#endif + +typedef PD_LONGINTTYPE t_int; /* pointer-size integer */ +typedef PD_FLOATTYPE t_float; /* a float type at most the same size */ +typedef PD_FLOATTYPE t_floatarg; /* float type for function calls */ + +typedef struct _symbol +{ + char *s_name; + struct _class **s_thing; + struct _symbol *s_next; +} t_symbol; + +EXTERN_STRUCT _array; +#define t_array struct _array /* g_canvas.h */ + +/* pointers to glist and array elements go through a "stub" which sticks +around after the glist or array is freed. The stub itself is deleted when +both the glist/array is gone and the refcount is zero, ensuring that no +gpointers are pointing here. */ + +#define GP_NONE 0 /* the stub points nowhere (has been cut off) */ +#define GP_GLIST 1 /* the stub points to a glist element */ +#define GP_ARRAY 2 /* ... or array */ + +typedef struct _gstub +{ + union + { + struct _glist *gs_glist; /* glist we're in */ + struct _array *gs_array; /* array we're in */ + } gs_un; + int gs_which; /* GP_GLIST/GP_ARRAY */ + int gs_refcount; /* number of gpointers pointing here */ +} t_gstub; + +typedef struct _gpointer /* pointer to a gobj in a glist */ +{ + union + { + struct _scalar *gp_scalar; /* scalar we're in (if glist) */ + union word *gp_w; /* raw data (if array) */ + } gp_un; + int gp_valid; /* number which must match gpointee */ + t_gstub *gp_stub; /* stub which points to glist/array */ +} t_gpointer; + +typedef union word +{ + t_float w_float; + t_symbol *w_symbol; + t_gpointer *w_gpointer; + t_array *w_array; + struct _binbuf *w_binbuf; + int w_index; +} t_word; + +typedef enum +{ + A_NULL, + A_FLOAT, + A_SYMBOL, + A_POINTER, + A_SEMI, + A_COMMA, + A_DEFFLOAT, + A_DEFSYM, + A_DOLLAR, + A_DOLLSYM, + A_GIMME, + A_CANT +} t_atomtype; + +#define A_DEFSYMBOL A_DEFSYM /* better name for this */ + +typedef struct _atom +{ + t_atomtype a_type; + union word a_w; +} t_atom; + +EXTERN_STRUCT _class; +#define t_class struct _class + +EXTERN_STRUCT _outlet; +#define t_outlet struct _outlet + +EXTERN_STRUCT _inlet; +#define t_inlet struct _inlet + +EXTERN_STRUCT _binbuf; +#define t_binbuf struct _binbuf + +EXTERN_STRUCT _clock; +#define t_clock struct _clock + +EXTERN_STRUCT _outconnect; +#define t_outconnect struct _outconnect + +EXTERN_STRUCT _glist; +#define t_glist struct _glist +#define t_canvas struct _glist /* LATER lose this */ + +typedef t_class *t_pd; /* pure datum: nothing but a class pointer */ + +typedef struct _gobj /* a graphical object */ +{ + t_pd g_pd; /* pure datum header (class) */ + struct _gobj *g_next; /* next in list */ +} t_gobj; + +typedef struct _scalar /* a graphical object holding data */ +{ + t_gobj sc_gobj; /* header for graphical object */ + t_symbol *sc_template; /* template name (LATER replace with pointer) */ + t_word sc_vec[1]; /* indeterminate-length array of words */ +} t_scalar; + +typedef struct _text /* patchable object - graphical, with text */ +{ + t_gobj te_g; /* header for graphical object */ + t_binbuf *te_binbuf; /* holder for the text */ + t_outlet *te_outlet; /* linked list of outlets */ + t_inlet *te_inlet; /* linked list of inlets */ + short te_xpix; /* x&y location (within the toplevel) */ + short te_ypix; + short te_width; /* requested width in chars, 0 if auto */ + unsigned int te_type:2; /* from defs below */ +} t_text; + +#define T_TEXT 0 /* just a textual comment */ +#define T_OBJECT 1 /* a MAX style patchable object */ +#define T_MESSAGE 2 /* a MAX type message */ +#define T_ATOM 3 /* a cell to display a number or symbol */ + +#define te_pd te_g.g_pd + + /* t_object is synonym for t_text (LATER unify them) */ + +typedef struct _text t_object; + +#define ob_outlet te_outlet +#define ob_inlet te_inlet +#define ob_binbuf te_binbuf +#define ob_pd te_g.g_pd +#define ob_g te_g + +typedef void (*t_method)(void); +typedef void *(*t_newmethod)( void); + +/* in ARM 64 a varargs prototype generates a different function call sequence +from a fixed one, so in that special case we make a more restrictive +definition for t_gotfn. This will break some code in the "chaos" package +in Pd extended. (that code will run incorrectly anyhow so why not catch it +at compile time anyhow.) */ +#if defined(__APPLE__) && defined(__aarch64__) +typedef void (*t_gotfn)(void *x); +#else +typedef void (*t_gotfn)(void *x, ...); +#endif + +/* ---------------- pre-defined objects and symbols --------------*/ +EXTERN t_pd pd_objectmaker; /* factory for creating "object" boxes */ +EXTERN t_pd pd_canvasmaker; /* factory for creating canvases */ + +/* --------- prototypes from the central message system ----------- */ +EXTERN void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv); +EXTERN void pd_forwardmess(t_pd *x, int argc, t_atom *argv); +EXTERN t_symbol *gensym(const char *s); +EXTERN t_gotfn getfn(t_pd *x, t_symbol *s); +EXTERN t_gotfn zgetfn(t_pd *x, t_symbol *s); +EXTERN void nullfn(void); +EXTERN void pd_vmess(t_pd *x, t_symbol *s, char *fmt, ...); + +/* the following macros are for sending non-type-checkable messages, i.e., +using function lookup but circumventing type checking on arguments. Only +use for internal messaging protected by A_CANT so that the message can't +be generated at patch level. */ +#define mess0(x, s) ((*getfn((x), (s)))((x))) +typedef void (*t_gotfn1)(void *x, void *arg1); +#define mess1(x, s, a) ((*(t_gotfn1)getfn((x), (s)))((x), (a))) +typedef void (*t_gotfn2)(void *x, void *arg1, void *arg2); +#define mess2(x, s, a,b) ((*(t_gotfn2)getfn((x), (s)))((x), (a),(b))) +typedef void (*t_gotfn3)(void *x, void *arg1, void *arg2, void *arg3); +#define mess3(x, s, a,b,c) ((*(t_gotfn3)getfn((x), (s)))((x), (a),(b),(c))) +typedef void (*t_gotfn4)(void *x, + void *arg1, void *arg2, void *arg3, void *arg4); +#define mess4(x, s, a,b,c,d) \ + ((*(t_gotfn4)getfn((x), (s)))((x), (a),(b),(c),(d))) +typedef void (*t_gotfn5)(void *x, + void *arg1, void *arg2, void *arg3, void *arg4, void *arg5); +#define mess5(x, s, a,b,c,d,e) \ + ((*(t_gotfn5)getfn((x), (s)))((x), (a),(b),(c),(d),(e))) + +EXTERN void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv); +EXTERN t_pd *pd_newest(void); + +/* --------------- memory management -------------------- */ +EXTERN void *getbytes(size_t nbytes); +EXTERN void *getzbytes(size_t nbytes); +EXTERN void *copybytes(void *src, size_t nbytes); +EXTERN void freebytes(void *x, size_t nbytes); +EXTERN void *resizebytes(void *x, size_t oldsize, size_t newsize); + +/* -------------------- atoms ----------------------------- */ + +#define SETSEMI(atom) ((atom)->a_type = A_SEMI, (atom)->a_w.w_index = 0) +#define SETCOMMA(atom) ((atom)->a_type = A_COMMA, (atom)->a_w.w_index = 0) +#define SETPOINTER(atom, gp) ((atom)->a_type = A_POINTER, \ + (atom)->a_w.w_gpointer = (gp)) +#define SETFLOAT(atom, f) ((atom)->a_type = A_FLOAT, (atom)->a_w.w_float = (f)) +#define SETSYMBOL(atom, s) ((atom)->a_type = A_SYMBOL, \ + (atom)->a_w.w_symbol = (s)) +#define SETDOLLAR(atom, n) ((atom)->a_type = A_DOLLAR, \ + (atom)->a_w.w_index = (n)) +#define SETDOLLSYM(atom, s) ((atom)->a_type = A_DOLLSYM, \ + (atom)->a_w.w_symbol= (s)) + +EXTERN t_float atom_getfloat(t_atom *a); +EXTERN t_int atom_getint(t_atom *a); +EXTERN t_symbol *atom_getsymbol(t_atom *a); +EXTERN t_symbol *atom_gensym(t_atom *a); +EXTERN t_float atom_getfloatarg(int which, int argc, t_atom *argv); +EXTERN t_int atom_getintarg(int which, int argc, t_atom *argv); +EXTERN t_symbol *atom_getsymbolarg(int which, int argc, t_atom *argv); + +EXTERN void atom_string(t_atom *a, char *buf, unsigned int bufsize); + +/* ------------------ binbufs --------------- */ + +EXTERN t_binbuf *binbuf_new(void); +EXTERN void binbuf_free(t_binbuf *x); +EXTERN t_binbuf *binbuf_duplicate(t_binbuf *y); + +EXTERN void binbuf_text(t_binbuf *x, const char *text, size_t size); +EXTERN void binbuf_gettext(t_binbuf *x, char **bufp, int *lengthp); +EXTERN void binbuf_clear(t_binbuf *x); +EXTERN void binbuf_add(t_binbuf *x, int argc, t_atom *argv); +EXTERN void binbuf_addv(t_binbuf *x, char *fmt, ...); +EXTERN void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y); +EXTERN void binbuf_addsemi(t_binbuf *x); +EXTERN void binbuf_restore(t_binbuf *x, int argc, t_atom *argv); +EXTERN void binbuf_print(t_binbuf *x); +EXTERN int binbuf_getnatom(t_binbuf *x); +EXTERN t_atom *binbuf_getvec(t_binbuf *x); +EXTERN int binbuf_resize(t_binbuf *x, int newsize); +EXTERN void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv); +EXTERN int binbuf_read(t_binbuf *b, char *filename, char *dirname, + int crflag); +EXTERN int binbuf_read_via_canvas(t_binbuf *b, char *filename, t_canvas *canvas, + int crflag); +EXTERN int binbuf_read_via_path(t_binbuf *b, char *filename, char *dirname, + int crflag); +EXTERN int binbuf_write(t_binbuf *x, char *filename, char *dir, + int crflag); +EXTERN void binbuf_evalfile(t_symbol *name, t_symbol *dir); +EXTERN t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, + int tonew); + +/* ------------------ clocks --------------- */ + +EXTERN t_clock *clock_new(void *owner, t_method fn); +EXTERN void clock_set(t_clock *x, double systime); +EXTERN void clock_delay(t_clock *x, double delaytime); +EXTERN void clock_unset(t_clock *x); +EXTERN void clock_setunit(t_clock *x, double timeunit, int sampflag); +EXTERN double clock_getlogicaltime(void); +EXTERN double clock_getsystime(void); /* OBSOLETE; use clock_getlogicaltime() */ +EXTERN double clock_gettimesince(double prevsystime); +EXTERN double clock_gettimesincewithunits(double prevsystime, + double units, int sampflag); +EXTERN double clock_getsystimeafter(double delaytime); +EXTERN void clock_free(t_clock *x); + +/* ----------------- pure data ---------------- */ +EXTERN t_pd *pd_new(t_class *cls); +EXTERN void pd_free(t_pd *x); +EXTERN void pd_bind(t_pd *x, t_symbol *s); +EXTERN void pd_unbind(t_pd *x, t_symbol *s); +EXTERN t_pd *pd_findbyclass(t_symbol *s, t_class *c); +EXTERN void pd_pushsym(t_pd *x); +EXTERN void pd_popsym(t_pd *x); +EXTERN t_symbol *pd_getfilename(void); +EXTERN t_symbol *pd_getdirname(void); +EXTERN void pd_bang(t_pd *x); +EXTERN void pd_pointer(t_pd *x, t_gpointer *gp); +EXTERN void pd_float(t_pd *x, t_float f); +EXTERN void pd_symbol(t_pd *x, t_symbol *s); +EXTERN void pd_list(t_pd *x, t_symbol *s, int argc, t_atom *argv); +EXTERN void pd_anything(t_pd *x, t_symbol *s, int argc, t_atom *argv); +#define pd_class(x) (*(x)) + +/* ----------------- pointers ---------------- */ +EXTERN void gpointer_init(t_gpointer *gp); +EXTERN void gpointer_copy(const t_gpointer *gpfrom, t_gpointer *gpto); +EXTERN void gpointer_unset(t_gpointer *gp); +EXTERN int gpointer_check(const t_gpointer *gp, int headok); + +/* ----------------- patchable "objects" -------------- */ +EXTERN t_inlet *inlet_new(t_object *owner, t_pd *dest, t_symbol *s1, + t_symbol *s2); +EXTERN t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp); +EXTERN t_inlet *floatinlet_new(t_object *owner, t_float *fp); +EXTERN t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp); +EXTERN t_inlet *signalinlet_new(t_object *owner, t_float f); +EXTERN void inlet_free(t_inlet *x); + +EXTERN t_outlet *outlet_new(t_object *owner, t_symbol *s); +EXTERN void outlet_bang(t_outlet *x); +EXTERN void outlet_pointer(t_outlet *x, t_gpointer *gp); +EXTERN void outlet_float(t_outlet *x, t_float f); +EXTERN void outlet_symbol(t_outlet *x, t_symbol *s); +EXTERN void outlet_list(t_outlet *x, t_symbol *s, int argc, t_atom *argv); +EXTERN void outlet_anything(t_outlet *x, t_symbol *s, int argc, t_atom *argv); +EXTERN t_symbol *outlet_getsymbol(t_outlet *x); +EXTERN void outlet_free(t_outlet *x); +EXTERN t_object *pd_checkobject(t_pd *x); + + +/* -------------------- canvases -------------- */ + +EXTERN void glob_setfilename(void *dummy, t_symbol *name, t_symbol *dir); + +EXTERN void canvas_setargs(int argc, t_atom *argv); +EXTERN void canvas_getargs(int *argcp, t_atom **argvp); +EXTERN t_symbol *canvas_getcurrentdir(void); +EXTERN t_glist *canvas_getcurrent(void); +EXTERN void canvas_makefilename(t_glist *c, char *file, + char *result,int resultsize); +EXTERN t_symbol *canvas_getdir(t_glist *x); +EXTERN char sys_font[]; /* default typeface set in s_main.c */ +EXTERN char sys_fontweight[]; /* default font weight set in s_main.c */ +EXTERN int sys_hostfontsize(int fontsize, int zoom); +EXTERN int sys_zoomfontwidth(int fontsize, int zoom, int worstcase); +EXTERN int sys_zoomfontheight(int fontsize, int zoom, int worstcase); +EXTERN int sys_fontwidth(int fontsize); +EXTERN int sys_fontheight(int fontsize); +EXTERN void canvas_dataproperties(t_glist *x, t_scalar *sc, t_binbuf *b); +EXTERN int canvas_open(t_canvas *x, const char *name, const char *ext, + char *dirresult, char **nameresult, unsigned int size, int bin); + +/* ---------------- widget behaviors ---------------------- */ + +EXTERN_STRUCT _widgetbehavior; +#define t_widgetbehavior struct _widgetbehavior + +EXTERN_STRUCT _parentwidgetbehavior; +#define t_parentwidgetbehavior struct _parentwidgetbehavior +EXTERN const t_parentwidgetbehavior *pd_getparentwidget(t_pd *x); + +/* -------------------- classes -------------- */ + +#define CLASS_DEFAULT 0 /* flags for new classes below */ +#define CLASS_PD 1 +#define CLASS_GOBJ 2 +#define CLASS_PATCHABLE 3 +#define CLASS_NOINLET 8 + +#define CLASS_TYPEMASK 3 + + +EXTERN t_class *class_new(t_symbol *name, t_newmethod newmethod, + t_method freemethod, size_t size, int flags, t_atomtype arg1, ...); +EXTERN void class_addcreator(t_newmethod newmethod, t_symbol *s, + t_atomtype type1, ...); +EXTERN void class_addmethod(t_class *c, t_method fn, t_symbol *sel, + t_atomtype arg1, ...); +EXTERN void class_addbang(t_class *c, t_method fn); +EXTERN void class_addpointer(t_class *c, t_method fn); +EXTERN void class_doaddfloat(t_class *c, t_method fn); +EXTERN void class_addsymbol(t_class *c, t_method fn); +EXTERN void class_addlist(t_class *c, t_method fn); +EXTERN void class_addanything(t_class *c, t_method fn); +EXTERN void class_sethelpsymbol(t_class *c, t_symbol *s); +EXTERN void class_setwidget(t_class *c, const t_widgetbehavior *w); +EXTERN void class_setparentwidget(t_class *c, const t_parentwidgetbehavior *w); +EXTERN const t_parentwidgetbehavior *class_parentwidget(t_class *c); +EXTERN char *class_getname(t_class *c); +EXTERN char *class_gethelpname(t_class *c); +EXTERN char *class_gethelpdir(t_class *c); +EXTERN void class_setdrawcommand(t_class *c); +EXTERN int class_isdrawcommand(t_class *c); +EXTERN void class_domainsignalin(t_class *c, int onset); +EXTERN void class_set_extern_dir(t_symbol *s); +#define CLASS_MAINSIGNALIN(c, type, field) \ + class_domainsignalin(c, (char *)(&((type *)0)->field) - (char *)0) + + /* prototype for functions to save Pd's to a binbuf */ +typedef void (*t_savefn)(t_gobj *x, t_binbuf *b); +EXTERN void class_setsavefn(t_class *c, t_savefn f); +EXTERN t_savefn class_getsavefn(t_class *c); +EXTERN void obj_saveformat(t_object *x, t_binbuf *bb); /* add format to bb */ + + /* prototype for functions to open properties dialogs */ +typedef void (*t_propertiesfn)(t_gobj *x, struct _glist *glist); +EXTERN void class_setpropertiesfn(t_class *c, t_propertiesfn f); +EXTERN t_propertiesfn class_getpropertiesfn(t_class *c); + +#ifndef PD_CLASS_DEF +#define class_addbang(x, y) class_addbang((x), (t_method)(y)) +#define class_addpointer(x, y) class_addpointer((x), (t_method)(y)) +#define class_addfloat(x, y) class_doaddfloat((x), (t_method)(y)) +#define class_addsymbol(x, y) class_addsymbol((x), (t_method)(y)) +#define class_addlist(x, y) class_addlist((x), (t_method)(y)) +#define class_addanything(x, y) class_addanything((x), (t_method)(y)) +#endif + +/* ------------ printing --------------------------------- */ +EXTERN void post(const char *fmt, ...); +EXTERN void startpost(const char *fmt, ...); +EXTERN void poststring(const char *s); +EXTERN void postfloat(t_floatarg f); +EXTERN void postatom(int argc, t_atom *argv); +EXTERN void endpost(void); +EXTERN void error(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2); +EXTERN void verbose(int level, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(2, 3); +EXTERN void bug(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2); +EXTERN void pd_error(void *object, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(2, 3); +EXTERN void logpost(const void *object, const int level, const char *fmt, ...) + ATTRIBUTE_FORMAT_PRINTF(3, 4); +EXTERN void sys_logerror(const char *object, const char *s); +EXTERN void sys_unixerror(const char *object); +EXTERN void sys_ouch(void); + + +/* ------------ system interface routines ------------------- */ +EXTERN int sys_isreadablefile(const char *name); +EXTERN int sys_isabsolutepath(const char *dir); +EXTERN void sys_bashfilename(const char *from, char *to); +EXTERN void sys_unbashfilename(const char *from, char *to); +EXTERN int open_via_path(const char *dir, const char *name, const char *ext, + char *dirresult, char **nameresult, unsigned int size, int bin); +EXTERN int sched_geteventno(void); +EXTERN double sys_getrealtime(void); +EXTERN int (*sys_idlehook)(void); /* hook to add idle time computation */ + +/* Win32's open()/fopen() do not handle UTF-8 filenames so we need + * these internal versions that handle UTF-8 filenames the same across + * all platforms. They are recommended for use in external + * objectclasses as well so they work with Unicode filenames on Windows */ +EXTERN int sys_open(const char *path, int oflag, ...); +EXTERN int sys_close(int fd); +EXTERN FILE *sys_fopen(const char *filename, const char *mode); +EXTERN int sys_fclose(FILE *stream); + +/* ------------ threading ------------------- */ +EXTERN void sys_lock(void); +EXTERN void sys_unlock(void); +EXTERN int sys_trylock(void); + + +/* --------------- signals ----------------------------------- */ + +typedef PD_FLOATTYPE t_sample; +typedef union _sampleint_union { + t_sample f; + PD_FLOATUINTTYPE i; +} t_sampleint_union; +#define MAXLOGSIG 32 +#define MAXSIGSIZE (1 << MAXLOGSIG) + +typedef struct _signal +{ + int s_n; /* number of points in the array */ + t_sample *s_vec; /* the array */ + t_float s_sr; /* sample rate */ + int s_refcount; /* number of times used */ + int s_isborrowed; /* whether we're going to borrow our array */ + struct _signal *s_borrowedfrom; /* signal to borrow it from */ + struct _signal *s_nextfree; /* next in freelist */ + struct _signal *s_nextused; /* next in used list */ + int s_vecsize; /* allocated size of array in points */ +} t_signal; + +typedef t_int *(*t_perfroutine)(t_int *args); + +EXTERN t_int *plus_perform(t_int *args); +EXTERN t_int *zero_perform(t_int *args); +EXTERN t_int *copy_perform(t_int *args); + +EXTERN void dsp_add_plus(t_sample *in1, t_sample *in2, t_sample *out, int n); +EXTERN void dsp_add_copy(t_sample *in, t_sample *out, int n); +EXTERN void dsp_add_scalarcopy(t_float *in, t_sample *out, int n); +EXTERN void dsp_add_zero(t_sample *out, int n); + +EXTERN int sys_getblksize(void); +EXTERN t_float sys_getsr(void); +EXTERN int sys_get_inchannels(void); +EXTERN int sys_get_outchannels(void); + +EXTERN void dsp_add(t_perfroutine f, int n, ...); +EXTERN void dsp_addv(t_perfroutine f, int n, t_int *vec); +EXTERN void pd_fft(t_float *buf, int npoints, int inverse); +EXTERN int ilog2(int n); + +EXTERN void mayer_fht(t_sample *fz, int n); +EXTERN void mayer_fft(int n, t_sample *real, t_sample *imag); +EXTERN void mayer_ifft(int n, t_sample *real, t_sample *imag); +EXTERN void mayer_realfft(int n, t_sample *real); +EXTERN void mayer_realifft(int n, t_sample *real); + +EXTERN float *cos_table; +#define LOGCOSTABSIZE 9 +#define COSTABSIZE (1<> 1) & 0x20000000)); +} + +#elif PD_FLOATSIZE == 64 + +typedef union +{ + t_float f; + unsigned int ui[2]; +}t_bigorsmall64; + +static inline int PD_BADFLOAT(t_float f) /* malformed double */ +{ + t_bigorsmall64 pun; + pun.f = f; + pun.ui[1] &= 0x7ff00000; + return((pun.ui[1] == 0) | (pun.ui[1] == 0x7ff00000)); +} + +static inline int PD_BIGORSMALL(t_float f) /* exponent outside (-512,512) */ +{ + t_bigorsmall64 pun; + pun.f = f; + return((pun.ui[1] & 0x20000000) == ((pun.ui[1] >> 1) & 0x20000000)); +} + +#endif /* PD_FLOATSIZE */ +#else /* not INTEL or ARM */ +#define PD_BADFLOAT(f) 0 +#define PD_BIGORSMALL(f) 0 +#endif + +#else /* _MSC_VER */ +#if PD_FLOATSIZE == 32 +#define PD_BADFLOAT(f) ((((*(unsigned int*)&(f))&0x7f800000)==0) || \ + (((*(unsigned int*)&(f))&0x7f800000)==0x7f800000)) +/* more stringent test: anything not between 1e-19 and 1e19 in absolute val */ +#define PD_BIGORSMALL(f) ((((*(unsigned int*)&(f))&0x60000000)==0) || \ + (((*(unsigned int*)&(f))&0x60000000)==0x60000000)) +#else /* 64 bits... don't know what to do here */ +#define PD_BADFLOAT(f) (!(((f) >= 0) || ((f) <= 0))) +#define PD_BIGORSMALL(f) ((f) > 1e150 || (f) < -1e150 \ + || (f) > -1e-150 && (f) < 1e-150 ) +#endif +#endif /* _MSC_VER */ + /* get version number at run time */ +EXTERN void sys_getversion(int *major, int *minor, int *bugfix); + +EXTERN_STRUCT _instancemidi; +#define t_instancemidi struct _instancemidi + +EXTERN_STRUCT _instanceinter; +#define t_instanceinter struct _instanceinter + +EXTERN_STRUCT _instancecanvas; +#define t_instancecanvas struct _instancecanvas + +EXTERN_STRUCT _instanceugen; +#define t_instanceugen struct _instanceugen + +EXTERN_STRUCT _instancestuff; +#define t_instancestuff struct _instancestuff + +#ifndef PDTHREADS +#define PDTHREADS 1 +#endif + +struct _pdinstance +{ + double pd_systime; /* global time in Pd ticks */ + t_clock *pd_clock_setlist; /* list of set clocks */ + t_canvas *pd_canvaslist; /* list of all root canvases */ + int pd_instanceno; /* ordinal number of this instance */ + t_symbol **pd_symhash; /* symbol table hash table */ + t_instancemidi *pd_midi; /* private stuff for x_midi.c */ + t_instanceinter *pd_inter; /* private stuff for s_inter.c */ + t_instanceugen *pd_ugen; /* private stuff for d_ugen.c */ + t_instancecanvas *pd_gui; /* semi-private stuff in g_canvas.h */ + t_instancestuff *pd_stuff; /* semi-private stuff in s_stuff.h */ + t_pd *pd_newest; /* most recently created object */ +#ifdef PDINSTANCE + t_symbol pd_s_pointer; + t_symbol pd_s_float; + t_symbol pd_s_symbol; + t_symbol pd_s_bang; + t_symbol pd_s_list; + t_symbol pd_s_anything; + t_symbol pd_s_signal; + t_symbol pd_s__N; + t_symbol pd_s__X; + t_symbol pd_s_x; + t_symbol pd_s_y; + t_symbol pd_s_; +#endif +#if PDTHREADS + int pd_islocked; +#endif +}; +#define t_pdinstance struct _pdinstance +EXTERN t_pdinstance pd_maininstance; + +/* m_pd.c */ +#ifdef PDINSTANCE +EXTERN t_pdinstance *pdinstance_new( void); +EXTERN void pd_setinstance(t_pdinstance *x); +EXTERN void pdinstance_free(t_pdinstance *x); +#endif /* PDINSTANCE */ + +#if defined(PDTHREADS) && defined(PDINSTANCE) +#ifdef _MSC_VER +#define PERTHREAD __declspec(thread) +#else +#define PERTHREAD __thread +#endif /* _MSC_VER */ +#else +#define PERTHREAD +#endif + +#ifdef PDINSTANCE +extern PERTHREAD t_pdinstance *pd_this; +EXTERN t_pdinstance **pd_instances; +EXTERN int pd_ninstances; +#else +#define pd_this (&pd_maininstance) +#endif /* PDINSTANCE */ + +#ifdef PDINSTANCE +#define s_pointer (pd_this->pd_s_pointer) +#define s_float (pd_this->pd_s_float) +#define s_symbol (pd_this->pd_s_symbol) +#define s_bang (pd_this->pd_s_bang) +#define s_list (pd_this->pd_s_list) +#define s_anything (pd_this->pd_s_anything) +#define s_signal (pd_this->pd_s_signal) +#define s__N (pd_this->pd_s__N) +#define s__X (pd_this->pd_s__X) +#define s_x (pd_this->pd_s_x) +#define s_y (pd_this->pd_s_y) +#define s_ (pd_this->pd_s_) +#else +EXTERN t_symbol s_pointer, s_float, s_symbol, s_bang, s_list, s_anything, + s_signal, s__N, s__X, s_x, s_y, s_; +#endif + +EXTERN t_canvas *pd_getcanvaslist(void); +EXTERN int pd_getdspstate(void); + +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) +} +#endif + +#define __m_pd_h_ +#endif /* __m_pd_h_ */ diff --git a/ports/camomile/source/LibPd/pure-data/src/m_sched.c b/ports/camomile/source/LibPd/pure-data/src/m_sched.c new file mode 100644 index 00000000..23ae2641 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/m_sched.c @@ -0,0 +1,620 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* scheduling stuff */ + +#include "m_pd.h" +#include "m_imp.h" +#include "s_stuff.h" +#ifdef _WIN32 +#include +#endif + + /* LATER consider making this variable. It's now the LCM of all sample + rates we expect to see: 32000, 44100, 48000, 88200, 96000. */ +#define TIMEUNITPERMSEC (32. * 441.) +#define TIMEUNITPERSECOND (TIMEUNITPERMSEC * 1000.) + +#define SYS_QUIT_QUIT 1 +#define SYS_QUIT_RESTART 2 +static int sys_quit; + +int sys_usecsincelastsleep(void); +int sys_sleepgrain; + +typedef void (*t_clockmethod)(void *client); + +struct _clock +{ + double c_settime; /* in TIMEUNITS; <0 if unset */ + void *c_owner; + t_clockmethod c_fn; + struct _clock *c_next; + t_float c_unit; /* >0 if in TIMEUNITS; <0 if in samples */ +}; + +#ifdef HAVE_UNISTD_H +#include +#endif + +t_clock *clock_new(void *owner, t_method fn) +{ + t_clock *x = (t_clock *)getbytes(sizeof *x); + x->c_settime = -1; + x->c_owner = owner; + x->c_fn = (t_clockmethod)fn; + x->c_next = 0; + x->c_unit = TIMEUNITPERMSEC; + return (x); +} + +void clock_unset(t_clock *x) +{ + if (x->c_settime >= 0) + { + if (x == pd_this->pd_clock_setlist) + pd_this->pd_clock_setlist = x->c_next; + else + { + t_clock *x2 = pd_this->pd_clock_setlist; + while (x2->c_next != x) x2 = x2->c_next; + x2->c_next = x->c_next; + } + x->c_settime = -1; + } +} + + /* set the clock to call back at an absolute system time */ +void clock_set(t_clock *x, double setticks) +{ + if (setticks < pd_this->pd_systime) setticks = pd_this->pd_systime; + clock_unset(x); + x->c_settime = setticks; + if (pd_this->pd_clock_setlist && + pd_this->pd_clock_setlist->c_settime <= setticks) + { + t_clock *cbefore, *cafter; + for (cbefore = pd_this->pd_clock_setlist, + cafter = pd_this->pd_clock_setlist->c_next; + cbefore; cbefore = cafter, cafter = cbefore->c_next) + { + if (!cafter || cafter->c_settime > setticks) + { + cbefore->c_next = x; + x->c_next = cafter; + return; + } + } + } + else x->c_next = pd_this->pd_clock_setlist, pd_this->pd_clock_setlist = x; +} + + /* set the clock to call back after a delay in msec */ +void clock_delay(t_clock *x, double delaytime) +{ + clock_set(x, (x->c_unit > 0 ? + pd_this->pd_systime + x->c_unit * delaytime : + pd_this->pd_systime - + (x->c_unit*(TIMEUNITPERSECOND/STUFF->st_dacsr)) * delaytime)); +} + + /* set the time unit in msec or (if 'samps' is set) in samples. This + is flagged by setting c_unit negative. If the clock is currently set, + recalculate the delay based on the new unit and reschedule */ +void clock_setunit(t_clock *x, double timeunit, int sampflag) +{ + double timeleft; + if (timeunit <= 0) + timeunit = 1; + /* if no change, return to avoid truncation errors recalculating delay */ + if ((sampflag && (timeunit == -x->c_unit)) || + (!sampflag && (timeunit == x->c_unit * TIMEUNITPERMSEC))) + return; + + /* figure out time left in the units we were in */ + timeleft = (x->c_settime < 0 ? -1 : + (x->c_settime - pd_this->pd_systime)/((x->c_unit > 0)? x->c_unit : + (x->c_unit*(TIMEUNITPERSECOND/STUFF->st_dacsr)))); + if (sampflag) + x->c_unit = -timeunit; /* negate to flag sample-based */ + else x->c_unit = timeunit * TIMEUNITPERMSEC; + if (timeleft >= 0) /* reschedule if already set */ + clock_delay(x, timeleft); +} + + /* get current logical time. We don't specify what units this is in; + use clock_gettimesince() to measure intervals from time of this call. */ +double clock_getlogicaltime( void) +{ + return (pd_this->pd_systime); +} + + /* OBSOLETE (misleading) function name kept for compatibility */ +double clock_getsystime( void) { return (pd_this->pd_systime); } + + /* elapsed time in milliseconds since the given system time */ +double clock_gettimesince(double prevsystime) +{ + return ((pd_this->pd_systime - prevsystime)/TIMEUNITPERMSEC); +} + + /* elapsed time in units, ala clock_setunit(), since given system time */ +double clock_gettimesincewithunits(double prevsystime, + double units, int sampflag) +{ + /* If in samples, divide TIMEUNITPERSECOND/sys_dacsr first (at + cost of an extra division) since it's probably an integer and if + units == 1 and (sys_time - prevsystime) is an integer number of + DSP ticks, the result will be exact. */ + if (sampflag) + return ((pd_this->pd_systime - prevsystime)/ + ((TIMEUNITPERSECOND/STUFF->st_dacsr)*units)); + else return ((pd_this->pd_systime - prevsystime)/(TIMEUNITPERMSEC*units)); +} + + /* what value the system clock will have after a delay */ +double clock_getsystimeafter(double delaytime) +{ + return (pd_this->pd_systime + TIMEUNITPERMSEC * delaytime); +} + +void clock_free(t_clock *x) +{ + clock_unset(x); + freebytes(x, sizeof *x); +} + +/* the following routines maintain a real-execution-time histogram of the +various phases of real-time execution. */ + +static int sys_bin[] = {0, 2, 5, 10, 20, 30, 50, 100, 1000}; +#define NBIN (sizeof(sys_bin)/sizeof(*sys_bin)) +#define NHIST 10 +static int sys_histogram[NHIST][NBIN]; +static double sys_histtime; +static int sched_diddsp, sched_didpoll, sched_didnothing; + +void sys_clearhist( void) +{ + unsigned int i, j; + for (i = 0; i < NHIST; i++) + for (j = 0; j < NBIN; j++) sys_histogram[i][j] = 0; + sys_histtime = sys_getrealtime(); + sched_diddsp = sched_didpoll = sched_didnothing = 0; +} + +void sys_printhist( void) +{ + unsigned int i, j; + for (i = 0; i < NHIST; i++) + { + int doit = 0; + for (j = 0; j < NBIN; j++) if (sys_histogram[i][j]) doit = 1; + if (doit) + { + post("%2d %8d %8d %8d %8d %8d %8d %8d %8d", i, + sys_histogram[i][0], + sys_histogram[i][1], + sys_histogram[i][2], + sys_histogram[i][3], + sys_histogram[i][4], + sys_histogram[i][5], + sys_histogram[i][6], + sys_histogram[i][7]); + } + } + post("dsp %d, pollgui %d, nothing %d", + sched_diddsp, sched_didpoll, sched_didnothing); +} + +static int sys_histphase; + +int sys_addhist(int phase) +{ + int i, j, phasewas = sys_histphase; + double newtime = sys_getrealtime(); + int msec = (newtime - sys_histtime) * 1000.; + for (j = NBIN-1; j >= 0; j--) + { + if (msec >= sys_bin[j]) + { + sys_histogram[phasewas][j]++; + break; + } + } + sys_histtime = newtime; + sys_histphase = phase; + return (phasewas); +} + +#define NRESYNC 20 + +typedef struct _resync +{ + int r_ntick; + int r_error; +} t_resync; + +static int oss_resyncphase = 0; +static int oss_nresync = 0; +static t_resync oss_resync[NRESYNC]; + + +static char *(oss_errornames[]) = { +"unknown", +"ADC blocked", +"DAC blocked", +"A/D/A sync", +"data late" +}; + +void glob_audiostatus(void) +{ + int dev, nresync, nresyncphase, i; + nresync = (oss_nresync >= NRESYNC ? NRESYNC : oss_nresync); + nresyncphase = oss_resyncphase - 1; + post("audio I/O error history:"); + post("seconds ago\terror type"); + for (i = 0; i < nresync; i++) + { + int errtype; + if (nresyncphase < 0) + nresyncphase += NRESYNC; + errtype = oss_resync[nresyncphase].r_error; + if (errtype < 0 || errtype > 4) + errtype = 0; + + post("%9.2f\t%s", + (sched_diddsp - oss_resync[nresyncphase].r_ntick) + * ((double)STUFF->st_schedblocksize) / STUFF->st_dacsr, + oss_errornames[errtype]); + nresyncphase--; + } +} + +static int sched_diored; +static int sched_dioredtime; +static int sched_meterson; + +void sys_log_error(int type) +{ + oss_resync[oss_resyncphase].r_ntick = sched_diddsp; + oss_resync[oss_resyncphase].r_error = type; + oss_nresync++; + if (++oss_resyncphase == NRESYNC) oss_resyncphase = 0; + if (type != ERR_NOTHING && !sched_diored && + (sched_diddsp >= sched_dioredtime)) + { + sys_vgui("pdtk_pd_dio 1\n"); + sched_diored = 1; + } + sched_dioredtime = + sched_diddsp + (int)(STUFF->st_dacsr /(double)STUFF->st_schedblocksize); +} + +static int sched_lastinclip, sched_lastoutclip, + sched_lastindb, sched_lastoutdb; + +void glob_watchdog(t_pd *dummy); + +static void sched_pollformeters( void) +{ + int inclip, outclip, indb, outdb; + static int sched_nextmeterpolltime, sched_nextpingtime; + + /* if there's no GUI but we're running in "realtime", here is + where we arrange to ping the watchdog every 2 seconds. */ +#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__) + if (!sys_havegui() && sys_hipriority && + (sched_diddsp - sched_nextpingtime > 0)) + { + glob_watchdog(0); + /* ping every 2 seconds */ + sched_nextpingtime = sched_diddsp + + 2 * (int)(STUFF->st_dacsr /(double)STUFF->st_schedblocksize); + } +#endif + + if (sched_diddsp - sched_nextmeterpolltime < 0) + return; + if (sched_diored && (sched_diddsp - sched_dioredtime > 0)) + { + sys_vgui("pdtk_pd_dio 0\n"); + sched_diored = 0; + } + if (sched_meterson) + { + t_sample inmax, outmax; + sys_getmeters(&inmax, &outmax); + indb = 0.5 + rmstodb(inmax); + outdb = 0.5 + rmstodb(outmax); + inclip = (inmax > 0.999); + outclip = (outmax >= 1.0); + } + else + { + indb = outdb = 0; + inclip = outclip = 0; + } + if (inclip != sched_lastinclip || outclip != sched_lastoutclip + || indb != sched_lastindb || outdb != sched_lastoutdb) + { + sys_vgui("pdtk_pd_meters %d %d %d %d\n", indb, outdb, inclip, outclip); + sched_lastinclip = inclip; + sched_lastoutclip = outclip; + sched_lastindb = indb; + sched_lastoutdb = outdb; + } + sched_nextmeterpolltime = + sched_diddsp + (int)(STUFF->st_dacsr /(double)STUFF->st_schedblocksize); +} + +void glob_meters(void *dummy, t_float f) +{ + if (f == 0) + sys_getmeters(0, 0); + sched_meterson = (f != 0); + sched_lastinclip = sched_lastoutclip = sched_lastindb = sched_lastoutdb = + -1; +} + +#if 0 +void glob_foo(void *dummy, t_symbol *s, int argc, t_atom *argv) +{ + if (argc) sys_clearhist(); + else sys_printhist(); +} +#endif + +void dsp_tick(void); + +static int sched_useaudio = SCHED_AUDIO_NONE; +static double sched_referencerealtime, sched_referencelogicaltime; + +void sched_reopenmeplease(void) /* request from s_audio for deferred reopen */ +{ + sys_quit = SYS_QUIT_RESTART; +} + +void sched_set_using_audio(int flag) +{ + sched_useaudio = flag; + if (flag == SCHED_AUDIO_NONE) + { + sched_referencerealtime = sys_getrealtime(); + sched_referencelogicaltime = clock_getlogicaltime(); + } + if (flag == SCHED_AUDIO_CALLBACK && + sched_useaudio != SCHED_AUDIO_CALLBACK) + sys_quit = SYS_QUIT_RESTART; + if (flag != SCHED_AUDIO_CALLBACK && + sched_useaudio == SCHED_AUDIO_CALLBACK) + post("sorry, can't turn off callbacks yet; restart Pd"); + /* not right yet! */ + + sys_vgui("pdtk_pd_audio %s\n", flag ? "on" : "off"); +} + + /* take the scheduler forward one DSP tick, also handling clock timeouts */ +void sched_tick( void) +{ + double next_sys_time = pd_this->pd_systime + + (STUFF->st_schedblocksize/STUFF->st_dacsr) * TIMEUNITPERSECOND; + int countdown = 5000; + while (pd_this->pd_clock_setlist && + pd_this->pd_clock_setlist->c_settime < next_sys_time) + { + t_clock *c = pd_this->pd_clock_setlist; + pd_this->pd_systime = c->c_settime; + clock_unset(pd_this->pd_clock_setlist); + outlet_setstacklim(); + (*c->c_fn)(c->c_owner); + if (!countdown--) + { + countdown = 5000; + sys_pollgui(); + } + if (sys_quit) + return; + } + pd_this->pd_systime = next_sys_time; + dsp_tick(); + sched_diddsp++; +} + +/* +Here is Pd's "main loop." This routine dispatches clock timeouts and DSP +"ticks" deterministically, and polls for input from MIDI and the GUI. If +we're left idle we also poll for graphics updates; but these are considered +lower priority than the rest. + +The time source is normally the audio I/O subsystem via the "sys_send_dacs()" +call. This call returns true if samples were transferred; false means that +the audio I/O system is still busy with previous transfers. +*/ + +void sys_pollmidiqueue( void); +void sys_initmidiqueue( void); + + /* sys_idlehook is a hook the user can fill in to grab idle time. Return +nonzero if you actually used the time; otherwise we're really really idle and +will now sleep. */ +int (*sys_idlehook)(void); + +static void m_pollingscheduler( void) +{ + int idlecount = 0; + + /* delete this when I'm sure it's not needed for back compatibility? */ + STUFF->st_time_per_dsp_tick = (TIMEUNITPERSECOND) * + ((double)STUFF->st_schedblocksize) / STUFF->st_dacsr; + sys_lock(); + sys_clearhist(); + if (sys_sleepgrain < 100) + sys_sleepgrain = sys_schedadvance/4; + if (sys_sleepgrain < 100) + sys_sleepgrain = 100; + else if (sys_sleepgrain > 5000) + sys_sleepgrain = 5000; + sys_initmidiqueue(); + while (!sys_quit) + { + int didsomething = 0; + int timeforward; + + sys_addhist(0); + waitfortick: + if (sched_useaudio != SCHED_AUDIO_NONE) + { + sys_unlock(); + timeforward = sys_send_dacs(); + sys_lock(); +#if 0 /* in linux and windoes, sometimes audio devices would freeze, which + in turn would freeze Pd. This code unfroze things by closing + audio in such cases. But this seems no longer necessary, and + on Macs at least, this seems to cause audio to get dropped if + the machine sleeps. */ + /* if dacs remain "idle" for 1 sec, they're hung up. */ + if (timeforward != 0) + idlecount = 0; + else + { + idlecount++; + if (!(idlecount & 31)) + { + static double idletime; + if (sched_useaudio != SCHED_AUDIO_POLL) + { + bug("m_pollingscheduler\n"); + return; + } + /* on 32nd idle, start a clock watch; every + 32 ensuing idles, check it */ + if (idlecount == 32) + idletime = sys_getrealtime(); + else if (sys_getrealtime() - idletime > 1.) + { + error("audio I/O stuck... closing audio\n"); + sys_close_audio(); + sched_set_using_audio(SCHED_AUDIO_NONE); + goto waitfortick; + } + } + } +#endif /* 0 */ + } + else + { + if (1000. * (sys_getrealtime() - sched_referencerealtime) + > clock_gettimesince(sched_referencelogicaltime)) + timeforward = SENDDACS_YES; + else timeforward = SENDDACS_NO; + } + sys_setmiditimediff(0, 1e-6 * sys_schedadvance); + sys_addhist(1); + if (timeforward != SENDDACS_NO) + sched_tick(); + if (timeforward == SENDDACS_YES) + didsomething = 1; + + sys_addhist(2); + sys_pollmidiqueue(); + if (sys_pollgui()) + { + if (!didsomething) + sched_didpoll++; + didsomething = 1; + } + sys_addhist(3); + /* test for idle; if so, do graphics updates. */ + if (!didsomething) + { + sched_pollformeters(); + sys_reportidle(); + sys_unlock(); /* unlock while we idle */ + /* call externally installed idle function if any. */ + if (!sys_idlehook || !sys_idlehook()) + { + /* if even that had nothing to do, sleep. */ + if (timeforward != SENDDACS_SLEPT) + sys_microsleep(sys_sleepgrain); + } + sys_lock(); + sys_addhist(5); + sched_didnothing++; + } + } + sys_unlock(); +} + +void sched_audio_callbackfn(void) +{ + sys_lock(); + sys_setmiditimediff(0, 1e-6 * sys_schedadvance); + sys_addhist(1); + sched_tick(); + sys_addhist(2); + sys_pollmidiqueue(); + sys_addhist(3); + sys_pollgui(); + sys_addhist(5); + sched_pollformeters(); + sys_addhist(0); + sys_unlock(); +} + +static void m_callbackscheduler(void) +{ + sys_initmidiqueue(); + while (!sys_quit) + { + double timewas = pd_this->pd_systime; +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + if (pd_this->pd_systime == timewas) + { + sys_lock(); + sys_pollgui(); + sched_tick(); + sys_unlock(); + } + if (sys_idlehook) + sys_idlehook(); + } +} + +int m_mainloop(void) +{ + while (sys_quit != SYS_QUIT_QUIT) + { + if (sched_useaudio == SCHED_AUDIO_CALLBACK) + m_callbackscheduler(); + else m_pollingscheduler(); + if (sys_quit == SYS_QUIT_RESTART) + { + sys_quit = 0; + if (audio_isopen()) + { + sys_close_audio(); + sys_reopen_audio(); + } + } + } + return (0); +} + +int m_batchmain(void) +{ + while (sys_quit != SYS_QUIT_QUIT) + sched_tick(); + return (0); +} + +void sys_exit(void) +{ + sys_quit = SYS_QUIT_QUIT; +} diff --git a/ports/camomile/source/LibPd/pure-data/src/makefile.gnu b/ports/camomile/source/LibPd/pure-data/src/makefile.gnu new file mode 100644 index 00000000..70e88d0c --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/makefile.gnu @@ -0,0 +1,271 @@ +# You can use this makefile to compile Pd for Gnu/linux. Masochists and +# packagers might prefer the automake route as described in ../README.txt +# You can invoke this one as: $ make -f makefile.gnu +# You don't have to "make install" - you can just invoke Pd from ../bin. +# +# targets include: +# all: pd, pd-watchdog, pdsend, pdreceive, and all extras. +# bin: just pd, pd-watchdog, pdsend, pdreceive. +# local-clean: clean up for "bin" target" +# clean: clean everything +# depend: c header dependencies +# tags: tags file +# install: install to /usr/local (or elsewhere by setting "prefix" variable) +# +# You can get jack support ($ make -f makfile.gnu JACK=TRUE) or compile in +# the portaudio library (PA=TRUE). By default, both ALSA and OSS (BSD style) +# audio APIs are compiled in. You can disable them (e.g., OSS=FALSE). In +# Gnu/linux, you can also just install "alsa-oss." +# +# You can add compiler flags using CODECFLAGS, MORECFLAGS and/or MORELDFLAGS. +# For example, you can turn off optimizing and enable debugging: CODECFLAGS=-g +# or compile with native double precision: MORECFLAGS=-DPD_FLOATSIZE=64 +# The MORECFLAGS variable is propagated to "extras" but CODECFLAGS and +# MORELDFLAGS are not. +# +# Packages you might need: +# tk-devel alsa-devel alsa-oss (unless you disable OSS). +# jack-audio-connection-kit-devel (if you want jack support) + +VPATH = ../obj:./ +OBJ_DIR = ../obj +BIN_DIR = ../bin +PDEXEC = $(BIN_DIR)/pd +EXT= pd_linux +ALSA=true +OSS=true + +prefix = /usr/local +exec_prefix = ${prefix} +bindir = ${exec_prefix}/bin +includedir = ${prefix}/include +libdir = ${exec_prefix}/lib +mandir = ${prefix}/share/man + +# varibles to match packages/Makefile.buildlayout so that they can be easily +# overridden when building Pd-extended builds. +libpddir = $(libdir)/pd +pddocdir = $(libpddir)/doc +libpdbindir = $(libpddir)/bin +libpdtcldir = $(libpddir)/tcl + +# The C flags are separated into CPPFLAGS, CODECFLAGS, and MORECFLAGS +# to allow easy overriding of CODECFLAGS and to allow adding MORECFLAGS: + +# C preprocessor flags, and flags controlling errors and warnings +CPPFLAGS = -DPD -DHAVE_LIBDL -DHAVE_UNISTD_H -DHAVE_ALLOCA_H \ + -DPDGUIDIR=\"tcl/\" \ + -D_LARGEFILE64_SOURCE -DINSTALL_PREFIX=\"$(prefix)\" \ + -Wall -W -Wstrict-prototypes -Wno-address\ + -Wno-unused -Wno-unused-parameter -Wno-parentheses -Wno-switch + +# code generation flags (e.g., optimization). +CODECFLAGS = -g -O3 -ffast-math -funroll-loops -fomit-frame-pointer + +# anything else you want to specify. Also passed on to "extra" makefiles. +MORECFLAGS = + +# "standard" flags for linker +LDFLAGS = -Wl,-export-dynamic + +# and another variable you can override to add more (like "-g"). +MORELDFLAGS = + +# libraries and system-dependent sources. +# These get added onto if JACK, etc., are defined below +LIB = -ldl -lm -lpthread +SYSSRC = s_midi_oss.c + +# conditionally add code and flags for various audio APIs +ifeq ($(ALSA), true) +CPPFLAGS += -DUSEAPI_ALSA +SYSSRC += s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c +LIB += -lasound +HAVEAUDIOAPI=true +endif +ifdef JACK +CPPFLAGS += -DUSEAPI_JACK +SYSSRC += s_audio_jack.c +LIB += -ljack +HAVEAUDIOAPI=true +endif +ifeq ($(OSS), true) +#error foo +CPPFLAGS += -DUSEAPI_OSS +SYSSRC += s_audio_oss.c +HAVEAUDIOAPI=true +endif +ifdef PA +CPPFLAGS += -DUSEAPI_PORTAUDIO +SYSSRC += s_audio_pa.c +LIB += -lportaudio +HAVEAUDIOAPI=true +endif +ifndef HAVEAUDIOAPI +CPPFLAGS += -DUSEAPI_DUMMY +SYSSRC += s_audio_dummy.c +endif + +CFLAGS = $(CPPFLAGS) $(CODECFLAGS) $(MORECFLAGS) + +SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \ + g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c g_clone.c \ + g_all_guis.c g_bang.c g_hdial.c g_hslider.c g_mycanvas.c g_numbox.c \ + g_toggle.c g_vdial.c g_vslider.c g_vumeter.c \ + m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \ + m_conf.c m_glob.c m_sched.c \ + s_main.c s_inter.c s_file.c s_print.c \ + s_loader.c s_path.c s_entry.c s_audio.c s_midi.c s_utf8.c s_audio_paring.c \ + d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \ + d_math.c d_fft.c d_fft_fftsg.c d_array.c d_global.c \ + d_delay.c d_resample.c d_soundfile.c \ + x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \ + x_time.c x_acoustics.c x_net.c x_text.c x_gui.c x_list.c x_array.c \ + x_scalar.c x_vexp.c x_vexp_if.c x_vexp_fun.c \ + $(SYSSRC) + +OBJ = $(SRC:.c=.o) + +# get version from m_pd.h to use in doc/1.manual/1.introduction.txt +PD_MAJOR_VERSION := $(shell grep PD_MAJOR_VERSION m_pd.h | \ + sed 's|^.define *PD_MAJOR_VERSION *\([0-9]*\).*|\1|' ) +PD_MINOR_VERSION := $(shell grep PD_MINOR_VERSION m_pd.h | \ + sed 's|^.define *PD_MINOR_VERSION *\([0-9]*\).*|\1|' ) +PD_BUGFIX_VERSION := $(shell grep PD_BUGFIX_VERSION m_pd.h | \ + sed 's|^.define *PD_BUGFIX_VERSION *\([0-9]*\).*|\1|' ) +PD_TEST_VERSION := $(shell grep PD_TEST_VERSION m_pd.h | \ + sed 's|^.define *PD_TEST_VERSION *"\(.*\)".*|\1|' ) +PD_VERSION := $(PD_MAJOR_VERSION).$(PD_MINOR_VERSION).$(PD_BUGFIX_VERSION) +ifneq ($(PD_TEST_VERSION),) + PD_VERSION := $(PD_VERSION)-$(PD_TEST_VERSION) +endif + +# +# ------------------ targets ------------------------------------ +# + +.PHONY: pd externs all depend + +all: pd $(BIN_DIR)/pd-watchdog $(BIN_DIR)/pdsend $(BIN_DIR)/pdreceive externs \ + makefile.dependencies + +bin: pd $(BIN_DIR)/pd-watchdog $(BIN_DIR)/pdsend $(BIN_DIR)/pdreceive + +$(OBJ) : %.o : %.c + $(CC) $(CFLAGS) $(INCLUDE) -c -o $(OBJ_DIR)/$*.o $*.c + +pd: $(PDEXEC) + +pd-watchdog: $(BIN_DIR)/pd-watchdog + +$(BIN_DIR)/pd-watchdog: s_watchdog.c + test -d $(BIN_DIR) || mkdir -p $(BIN_DIR) + $(CC) $(CFLAGS) -o $(BIN_DIR)/pd-watchdog s_watchdog.c + +$(BIN_DIR)/pdsend: u_pdsend.c + test -d $(BIN_DIR) || mkdir -p $(BIN_DIR) + $(CC) $(CFLAGS) -o $(BIN_DIR)/pdsend u_pdsend.c + +$(BIN_DIR)/pdreceive: u_pdreceive.c + test -d $(BIN_DIR) || mkdir -p $(BIN_DIR) + $(CC) $(CFLAGS) -o $(BIN_DIR)/pdreceive u_pdreceive.c + +$(PDEXEC): $(OBJ_DIR) $(OBJ) + test -d $(BIN_DIR) || mkdir -p $(BIN_DIR) + cd ../obj; $(CC) $(LDFLAGS) $(MORELDFLAGS) -o $(PDEXEC) $(OBJ) $(LIB) + +externs: + make -C ../extra/bonk~ MORECFLAGS="$(MORECFLAGS)" + make -C ../extra/choice MORECFLAGS="$(MORECFLAGS)" + make -C ../extra/fiddle~ MORECFLAGS="$(MORECFLAGS)" + make -C ../extra/loop~ MORECFLAGS="$(MORECFLAGS)" + make -C ../extra/lrshift~ MORECFLAGS="$(MORECFLAGS)" + make -C ../extra/pique MORECFLAGS="$(MORECFLAGS)" + make -C ../extra/sigmund~ MORECFLAGS="$(MORECFLAGS)" + make -C ../extra/pd~ MORECFLAGS="$(MORECFLAGS)" + make -C ../extra/stdout MORECFLAGS="$(MORECFLAGS)" + make -C ../extra/bob~ MORECFLAGS="$(MORECFLAGS)" + +BINARYMODE=-m755 + +ABOUT_FILE=$(DESTDIR)$(pddocdir)/1.manual/1.introduction.txt +install: all + install -d $(DESTDIR)$(libpdbindir) + install $(BIN_DIR)/pd-watchdog $(DESTDIR)$(libpdbindir)/pd-watchdog + install $(BINARYMODE) $(PDEXEC) $(DESTDIR)$(libpdbindir)/pd + install -d $(DESTDIR)$(bindir) + install $(BINARYMODE) $(PDEXEC) $(DESTDIR)$(bindir)/pd + install -m755 $(BIN_DIR)/pdsend $(DESTDIR)$(bindir)/pdsend + install -m755 $(BIN_DIR)/pdreceive $(DESTDIR)$(bindir)/pdreceive + install -d $(DESTDIR)$(libpdtcldir) + install ../tcl/* $(DESTDIR)$(libpdtcldir) + for dir in $(shell ls -1 ../doc | grep -v CVS); do \ + echo "installing $$dir"; \ + install -d $(DESTDIR)$(pddocdir)/$$dir ; \ + install -m644 -p ../doc/$$dir/*.* $(DESTDIR)$(pddocdir)/$$dir ; \ + done + for dir in $(shell ls -1 ../doc/7.stuff | grep -v CVS); do \ + echo "installing 7.stuff/$$dir"; \ + install -d $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \ + install -m644 -p ../doc/7.stuff/$$dir/*.* \ + $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \ + done + mv $(ABOUT_FILE) $(ABOUT_FILE).tmp + cat $(ABOUT_FILE).tmp | sed 's|PD_VERSION|Pd version $(PD_VERSION)|' \ + > $(ABOUT_FILE) + rm $(ABOUT_FILE).tmp + cp -pr ../extra $(DESTDIR)$(libpddir)/ + rm -f $(DESTDIR)$(libpddir)/extra/*/*.o + install -d $(DESTDIR)$(includedir) + install -m644 m_pd.h $(DESTDIR)$(includedir)/m_pd.h + install -d $(DESTDIR)$(mandir)/man1 + gzip < ../man/pd.1 > $(DESTDIR)$(mandir)/man1/pd.1.gz + chmod 644 $(DESTDIR)$(mandir)/man1/pd.1.gz + gzip < ../man/pdsend.1 > $(DESTDIR)$(mandir)/man1/pdsend.1.gz + chmod 644 $(DESTDIR)$(mandir)/man1/pdsend.1.gz + gzip < ../man/pdreceive.1 > $(DESTDIR)$(mandir)/man1/pdreceive.1.gz + chmod 644 $(DESTDIR)$(mandir)/man1/pdreceive.1.gz + @echo "Pd install succeeded." + +local-clean: + -rm -f ../obj/* $(BIN_DIR)/pd $(BIN_DIR)/pdsend \ + $(BIN_DIR)/pdreceive $(BIN_DIR)/pd-watchdog m_stamp.c \ + $(BIN_DIR)/*.tcl + -rm -f `find ../portaudio -name "*.o"` + -rm -f *~ + -(cd ../doc/6.externs; rm -f *.pd_linux) + -rm -f makefile.dependencies + +extra-clean: + -rm -f `find ../extra/ -name "*.pd_*"` + -rm -f tags + +clean: extra-clean local-clean + +distclean: clean + -rm -f config.cache config.log config.status makefile tags \ + autom4te.cache/output.* autom4te.cache/traces.* autom4te.cache/requests + -rmdir autom4te.cache + -rm -rf autom4te-*.cache + +tags: $(SRC) $(GSRC); ctags *.[ch] + +depend: makefile.dependencies + +$(OBJ_DIR): + test -d $(OBJ_DIR) || mkdir -p $(OBJ_DIR) + +makefile.dependencies: + $(CC) $(CPPFLAGS) -M $(SRC) > makefile.dependencies + +uninstall: + rm -f -r $(DESTDIR)$(libpddir) + rm -f $(DESTDIR)$(bindir)/pd + rm -f $(DESTDIR)$(bindir)/pdsend + rm -f $(DESTDIR)$(bindir)/pdreceive + rm -f $(DESTDIR)$(includedir)/m_pd.h + rm -f $(DESTDIR)$(mandir)/man1/pd.1.gz + rm -f $(DESTDIR)$(mandir)/man1/pdsend.1.gz + rm -f $(DESTDIR)$(mandir)/man1/pdreceive.1.gz + +-include makefile.dependencies diff --git a/ports/camomile/source/LibPd/pure-data/src/makefile.mac b/ports/camomile/source/LibPd/pure-data/src/makefile.mac new file mode 100644 index 00000000..72d95837 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/makefile.mac @@ -0,0 +1,242 @@ +# On Mac OS X, this needs to be defined to enable dlopen and weak linking +# support. Its safe on other platforms since gcc only checks this env var on +# Apple's gcc. +export MACOSX_DEPLOYMENT_TARGET = 10.3 + +VPATH = ../obj:./ +OBJ_DIR = ../obj +BIN_DIR = ../bin +PDEXEC = $(BIN_DIR)/pd +EXT= pd_darwin +GUINAME= libPdTcl.dylib +ARCH= -arch i386 -arch ppc +EXTRAARCH= -arch i386 -arch x86_64 -arch ppc + +prefix = /usr/local +exec_prefix = ${prefix} +bindir = ${exec_prefix}/bin +includedir = ${prefix}/include +libdir = ${exec_prefix}/lib +mandir = ${prefix}/man + +# varibles to match packages/Makefile.buildlayout so that they can be easily +# overridden when building Pd-extended builds. +libpddir = $(libdir)/pd +pddocdir = $(libpddir)/doc +libpdbindir = $(libpddir)/bin +libpdtcldir = $(libpddir)/tcl + +PADIR = ../portaudio/portaudio +PMDIR = ../portmidi/portmidi + +CPPFLAGS = -DPD -DINSTALL_PREFIX=\"$(prefix)\" \ + -DHAVE_LIBDL -DMACOSX -DHAVE_UNISTD_H -I/usr/X11R6/include \ + -I$(PADIR)/include -I$(PADIR)/src/common \ + -I$(PADIR)/src/os/mac_osx/ -I$(PMDIR)/pm_common \ + -I$(PMDIR)/pm_mac -I$(PMDIR)/porttime \ + -DUSEAPI_PORTAUDIO -DPA_USE_COREAUDIO -DNEWBUFFER +ARCH_CFLAGS = $(ARCH) +WARN_CFLAGS = -Wall -W -Wstrict-prototypes -Wno-unused -Wno-unused-parameter \ + -Wno-parentheses -Wno-switch +MORECFLAGS = -Wno-error -ffast-math -O3 + +LDFLAGS = -Wl -framework CoreAudio -framework AudioUnit \ + -framework AudioToolbox -framework Carbon -framework CoreMIDI $(ARCH) \ + +LIB = -ldl -lm -lpthread + +ifdef JACK +CPPFLAGS += -DUSEAPI_JACK +SYSSRC += s_audio_jack.c +LIB += -weak_framework Jackmp +endif + +CFLAGS = $(ARCH_CFLAGS) $(WARN_CFLAGS) $(CPPFLAGS) $(MORECFLAGS) + +# the sources + +SYSSRC += s_midi_pm.c s_audio_pa.c s_audio_paring.c \ + $(PADIR)/src/common/pa_allocation.c \ + $(PADIR)/src/common/pa_converters.c \ + $(PADIR)/src/common/pa_cpuload.c \ + $(PADIR)/src/common/pa_dither.c \ + $(PADIR)/src/common/pa_front.c \ + $(PADIR)/src/common/pa_process.c \ + $(PADIR)/src/common/pa_stream.c \ + $(PADIR)/src/common/pa_trace.c \ + $(PADIR)/src/common/pa_debugprint.c \ + $(PADIR)/src/common/pa_ringbuffer.c \ + $(PADIR)/src/os/unix/pa_unix_util.c \ + $(PADIR)/src/os/mac_osx/pa_mac_hostapis.c \ + $(PADIR)/src/hostapi/coreaudio/pa_mac_core.c \ + $(PADIR)/src/hostapi/coreaudio/pa_mac_core_blocking.c \ + $(PADIR)/src/hostapi/coreaudio/pa_mac_core_utilities.c \ + $(PMDIR)/pm_mac/pmmac.c \ + $(PMDIR)/pm_mac/pmmacosxcm.c \ + $(PMDIR)/pm_mac/finddefault.c \ + $(PMDIR)/pm_mac/readbinaryplist.c \ + $(PMDIR)/pm_common/pmutil.c \ + $(PMDIR)/pm_common/portmidi.c \ + $(PMDIR)/porttime/ptmacosx_cf.c + + +SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \ + g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c g_clone.c \ + g_all_guis.c g_bang.c g_hdial.c g_hslider.c g_mycanvas.c g_numbox.c \ + g_toggle.c g_vdial.c g_vslider.c g_vumeter.c \ + m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \ + m_conf.c m_glob.c m_sched.c \ + s_main.c s_inter.c s_file.c s_print.c \ + s_loader.c s_path.c s_entry.c s_audio.c s_midi.c s_utf8.c \ + d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \ + d_math.c d_fft.c d_fft_fftsg.c d_array.c d_global.c \ + d_delay.c d_resample.c d_soundfile.c \ + x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \ + x_time.c x_acoustics.c x_net.c x_text.c x_gui.c x_list.c x_array.c \ + x_scalar.c x_vexp.c x_vexp_if.c x_vexp_fun.c \ + $(SYSSRC) + +OBJ = $(SRC:.c=.o) + +# get version from m_pd.h to use in doc/1.manual/1.introduction.txt +PD_MAJOR_VERSION := $(shell grep PD_MAJOR_VERSION m_pd.h | \ + sed 's|^.define *PD_MAJOR_VERSION *\([0-9]*\).*|\1|' ) +PD_MINOR_VERSION := $(shell grep PD_MINOR_VERSION m_pd.h | \ + sed 's|^.define *PD_MINOR_VERSION *\([0-9]*\).*|\1|' ) +PD_BUGFIX_VERSION := $(shell grep PD_BUGFIX_VERSION m_pd.h | \ + sed 's|^.define *PD_BUGFIX_VERSION *\([0-9]*\).*|\1|' ) +PD_TEST_VERSION := $(shell grep PD_TEST_VERSION m_pd.h | \ + sed 's|^.define *PD_TEST_VERSION *"\(.*\)".*|\1|' ) +PD_VERSION := $(PD_MAJOR_VERSION).$(PD_MINOR_VERSION).$(PD_BUGFIX_VERSION) +ifneq ($(PD_TEST_VERSION),) + PD_VERSION := $(PD_VERSION)-$(PD_TEST_VERSION) +endif + +# +# ------------------ targets ------------------------------------ +# + +.PHONY: pd gui externs all + +all: pd $(BIN_DIR)/pd-watchdog gui $(BIN_DIR)/pdsend \ + $(BIN_DIR)/pdreceive externs + +bin: pd $(BIN_DIR)/pd-watchdog gui $(BIN_DIR)/pdsend \ + $(BIN_DIR)/pdreceive + +$(OBJ) : %.o : %.c + $(CC) $(CFLAGS) $(INCLUDE) -c -o $(OBJ_DIR)/$*.o $*.c + +pd: $(PDEXEC) + +pd-watchdog: $(BIN_DIR)/pd-watchdog + +$(BIN_DIR): + test -d $(BIN_DIR) || mkdir -p $(BIN_DIR) + +$(BIN_DIR)/pd-watchdog: s_watchdog.c $(BIN_DIR) + $(CC) $(CFLAGS) $(STRIPFLAG) -o $(BIN_DIR)/pd-watchdog s_watchdog.c + +$(BIN_DIR)/pdsend: u_pdsend.c $(BIN_DIR) + $(CC) $(CFLAGS) $(STRIPFLAG) -o $(BIN_DIR)/pdsend u_pdsend.c + +$(BIN_DIR)/pdreceive: u_pdreceive.c $(BIN_DIR) + $(CC) $(CFLAGS) $(STRIPFLAG) -o $(BIN_DIR)/pdreceive u_pdreceive.c + +$(PDEXEC): $(OBJ) $(BIN_DIR) + cd ../obj; $(CC) $(LDFLAGS) $(DBG_CFLAGS) -o $(PDEXEC) $(OBJ) $(LIB) + +externs: + make -C ../extra/bonk~ DARWINARCH="$(EXTRAARCH)" d_fat + make -C ../extra/choice DARWINARCH="$(EXTRAARCH)" d_fat + make -C ../extra/fiddle~ DARWINARCH="$(EXTRAARCH)" d_fat + make -C ../extra/loop~ DARWINARCH="$(EXTRAARCH)" d_fat + make -C ../extra/lrshift~ DARWINARCH="$(EXTRAARCH)" d_fat + make -C ../extra/pique DARWINARCH="$(EXTRAARCH)" d_fat + make -C ../extra/sigmund~ DARWINARCH="$(EXTRAARCH)" d_fat + make -C ../extra/pd~ DARWINARCH="$(EXTRAARCH)" d_fat + make -C ../extra/stdout DARWINARCH="$(EXTRAARCH)" d_fat + make -C ../extra/bob~ DARWINARCH="$(EXTRAARCH)" d_fat + +BINARYMODE=-m755 + +ABOUT_FILE=$(DESTDIR)$(pddocdir)/1.manual/1.introduction.txt +install: all + install -d $(DESTDIR)$(libpdbindir) + -install $(BIN_DIR)/$(GUINAME) $(DESTDIR)$(libpdbindir)/$(GUINAME) + install $(BIN_DIR)/pd-watchdog $(DESTDIR)$(libpdbindir)/pd-watchdog + install -d $(DESTDIR)$(bindir) + install $(BINARYMODE) $(PDEXEC) $(DESTDIR)$(bindir)/pd + install -m755 $(BIN_DIR)/pdsend $(DESTDIR)$(bindir)/pdsend + install -m755 $(BIN_DIR)/pdreceive $(DESTDIR)$(bindir)/pdreceive + install -d $(DESTDIR)$(libpdtcldir) + install ../tcl/* $(DESTDIR)$(libpdtcldir) + for dir in $(shell ls -1 ../doc | grep -v CVS); do \ + echo "installing $$dir"; \ + install -d $(DESTDIR)$(pddocdir)/$$dir ; \ + install -m644 -p ../doc/$$dir/*.* $(DESTDIR)$(pddocdir)/$$dir ; \ + done + for dir in $(shell ls -1 ../doc/7.stuff | grep -v CVS); do \ + echo "installing 7.stuff/$$dir"; \ + install -d $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \ + install -m644 -p ../doc/7.stuff/$$dir/*.* \ + $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \ + done + mv $(ABOUT_FILE) $(ABOUT_FILE).tmp + cat $(ABOUT_FILE).tmp | sed 's|PD_VERSION|Pd version $(PD_VERSION)|' \ + > $(ABOUT_FILE) + rm $(ABOUT_FILE).tmp + cp -pr ../extra $(DESTDIR)$(libpddir)/ + rm -f $(DESTDIR)$(libpddir)/extra/*/*.o + install -d $(DESTDIR)$(includedir) + install -m644 m_pd.h $(DESTDIR)$(includedir)/m_pd.h + install -d $(DESTDIR)$(mandir)/man1 + gzip < ../man/pd.1 > $(DESTDIR)$(mandir)/man1/pd.1.gz + chmod 644 $(DESTDIR)$(mandir)/man1/pd.1.gz + gzip < ../man/pdsend.1 > $(DESTDIR)$(mandir)/man1/pdsend.1.gz + chmod 644 $(DESTDIR)$(mandir)/man1/pdsend.1.gz + gzip < ../man/pdreceive.1 > $(DESTDIR)$(mandir)/man1/pdreceive.1.gz + chmod 644 $(DESTDIR)$(mandir)/man1/pdreceive.1.gz + @echo "Pd install succeeded." + +local-clean: + -rm -f ../obj/* $(BIN_DIR)/pd $(BIN_DIR)/pdsend \ + $(BIN_DIR)/pdreceive $(BIN_DIR)/pd-watchdog m_stamp.c \ + $(BIN_DIR)/*.tcl + -rm -f `find ../portaudio -name "*.o"` + -rm -f *~ + -(cd ../doc/6.externs; rm -f *.pd_linux) + -rm -f makefile.dependencies + touch makefile.dependencies + chmod 666 makefile.dependencies + +extra-clean: + -rm -f `find ../extra/ -name "*.pd_*"` + -rm -f tags + +clean: extra-clean local-clean + +distclean: clean + -rm -f config.cache config.log config.status makefile tags \ + autom4te.cache/output.* autom4te.cache/traces.* autom4te.cache/requests + -rmdir autom4te.cache + -rm -rf autom4te-*.cache + +tags: $(SRC) $(GSRC); ctags *.[ch] + +depend: makefile.dependencies + +makefile.dependencies: + $(CC) $(CPPFLAGS) -M $(SRC) > makefile.dependencies + +uninstall: + rm -f -r $(DESTDIR)$(libpddir) + rm -f $(DESTDIR)$(bindir)/pd + rm -f $(DESTDIR)$(bindir)/pdsend + rm -f $(DESTDIR)$(bindir)/pdreceive + rm -f $(DESTDIR)$(includedir)/m_pd.h + rm -f $(DESTDIR)$(mandir)/man1/pd.1.gz + rm -f $(DESTDIR)$(mandir)/man1/pdsend.1.gz + rm -f $(DESTDIR)$(mandir)/man1/pdreceive.1.gz + +include makefile.dependencies diff --git a/ports/camomile/source/LibPd/pure-data/src/makefile.mingw b/ports/camomile/source/LibPd/pure-data/src/makefile.mingw new file mode 100644 index 00000000..2476c6c1 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/makefile.mingw @@ -0,0 +1,318 @@ +# makefile to compile for windows using the mingw suite. +# To use this makefile to cross-compile from linux, type for example: +# make -f makefile.mingw CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-c++ \ +# WINDRES=i686-w64-mingw32-windres + +# Miller's Windows build uses Microsoft Visual C and makefile.msvc: +# http://lists.puredata.info/pipermail/pd-dev/2004-10/002981.html + +CC = gcc +CXX = g++ +WINDRES = windres + +cvs_root_dir = ../.. +pd_src = $(cvs_root_dir)/pd +DLL_DIR = $(pd_src)/src + +BIN_DIR = ../bin + +VPATH = $(pd_src)/src + +prefix = /usr/local/pd +exec_prefix = $(prefix) +includedir = $(prefix)/include +libdir = $(exec_prefix)/lib +mandir = $(prefix)/man +bindir = $(exec_prefix)/bin + +GFLAGS = -DINSTALL_PREFIX=\"$(prefix)\" + +# varibles to match packages/Makefile.buildlayout so that they can be easily +# overridden when building Pd-extended builds. +libpddir = $(prefix) +pddocdir = $(libpddir)/doc +libpdbindir = $(libpddir)/bin + +EXECDIR=../bin +PDEXEC = $(EXECDIR)/pd.exe +PDDLL = $(EXECDIR)/pd.dll +PDCOM = $(EXECDIR)/pd.com +PDRECEIVE = $(EXECDIR)/pdreceive.exe +PDSEND = $(EXECDIR)/pdsend.exe + +DLLWRAP= dllwrap + +MORECFLAGS = -O3 -funroll-loops -fomit-frame-pointer + +PADIR = $(pd_src)/portaudio/portaudio +ASIODIR = $(pd_src)/lib/ASIOSDK +ASIOINC = -I$(ASIODIR)/common -I$(ASIODIR)/host -I$(ASIODIR)/host/pc +INCPA = -I$(PADIR)/include -I$(PADIR)/src/common -I$(PADIR)/src/os/win \ + $(ASIOINC) +INCLUDE = -I$(pd_src)/src +GINCLUDE = -I/usr/local/include $(INCLUDE) + +LDFLAGS = +LIBS = -lm -lwsock32 -lwinmm -lole32 -lpthread \ + -static-libgcc -static-libstdc++ + +OPT_CFLAGS = + +WARN_CFLAGS = -Wall -W -Wstrict-prototypes -Wno-unused \ + -Wno-unused-parameter -Wno-parentheses -Wno-switch +# Some old code in asio/ASIOSDK/common/combase.h needs to be ignored, +# we do this by setting the WINVER macro to min Windows XP aka 5.1. +# Also, for SetDllDirectory() s_loader.c, we need a minium of Windows +# XP SP1. WINVER isnt' fine-grained enough for that, so we use the +# next minor version of Windows, 5.2. +ARCH_CFLAGS = -DPD -DPD_INTERNAL -DPA_USE_ASIO -DPA_USE_WMME -DWINVER=0x0502 \ + -DUSEAPI_MMIO -DUSEAPI_PORTAUDIO -mms-bitfields -DWISH='"wish85.exe"' + +CFLAGS += $(ARCH_CFLAGS) $(WARN_CFLAGS) $(OPT_CFLAGS) $(MORECFLAGS) + +STRIP = strip --strip-unneeded -R .note -R .comment + +# the sources + +PASRC = s_audio_pa.c s_audio_paring.c \ + s_audio_mmio.c \ + $(PADIR)/src/common/pa_stream.c \ + $(PADIR)/src/common/pa_trace.c \ + $(PADIR)/src/common/pa_process.c \ + $(PADIR)/src/common/pa_front.c \ + $(PADIR)/src/common/pa_dither.c \ + $(PADIR)/src/common/pa_cpuload.c \ + $(PADIR)/src/common/pa_converters.c \ + $(PADIR)/src/common/pa_allocation.c \ + $(PADIR)/src/common/pa_ringbuffer.c \ + $(PADIR)/src/os/win/pa_win_coinitialize.c \ + $(PADIR)/src/os/win/pa_win_hostapis.c \ + $(PADIR)/src/os/win/pa_win_util.c \ + $(PADIR)/src/os/win/pa_win_waveformat.c \ + $(PADIR)/src/hostapi/wmme/pa_win_wmme.c + +ASIOSRC = $(PADIR)/src/hostapi/asio/iasiothiscallresolver.cpp \ + $(PADIR)/src/hostapi/asio/pa_asio.cpp \ + $(ASIODIR)/common/asio.cpp \ + $(ASIODIR)/host/asiodrivers.cpp \ + $(ASIODIR)/host/pc/asiolist.cpp + +#VSRC = s_audio_vst.c + +PMDIR = ../portmidi/portmidi +PMINCLUDE = -I$(PMDIR)/pm_common -I$(PMDIR)/pm_win -I$(PMDIR)/porttime \ + -DNEWBUFFER +PMSRC = s_midi_pm.c \ + $(PMDIR)/pm_common/portmidi.c \ + $(PMDIR)/pm_common/pmutil.c \ + $(PMDIR)/porttime/porttime.c \ + $(PMDIR)/porttime/ptwinmm.c \ + $(PMDIR)/pm_win/pmwin.c \ + $(PMDIR)/pm_win/pmwinmm.c + +PMOBJ = $(PMSRC:.c=.o) + +HEADERS = g_all_guis.h m_imp.h g_canvas.h m_pd.h s_stuff.h \ + $(wildcard ../portaudio/common/*.h) s_audio_paring.h + +SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \ + g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c g_clone.c \ + g_all_guis.c g_bang.c g_hdial.c g_hslider.c g_mycanvas.c g_numbox.c \ + g_toggle.c g_vdial.c g_vslider.c g_vumeter.c \ + m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \ + m_conf.c m_glob.c m_sched.c \ + s_main.c s_inter.c s_file.c s_print.c \ + s_loader.c s_path.c s_entry.c s_audio.c s_midi.c s_utf8.c \ + d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \ + d_math.c d_fft.c d_fft_fftsg.c d_array.c d_global.c \ + d_delay.c d_resample.c d_soundfile.c \ + x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \ + x_time.c x_acoustics.c x_net.c x_text.c x_gui.c x_list.c x_array.c \ + x_scalar.c x_vexp.c x_vexp_if.c x_vexp_fun.c + +SRSRC = u_pdsend.c u_pdreceive.c + +OBJ = $(SRC:.c=.o) +SROBJ = $(SRSRC:.c=.o) +PAOBJ = $(PASRC:.c=.o) +ASIOOBJ = $(ASIOSRC:.cpp=.o) +#VOBJ = $(VSRC:.c=.o) +OBJC = $(OBJ) $(PAOBJ) $(ASIOOBJ) $(PMOBJ) + + +# get version from m_pd.h to use in doc/1.manual/1.introduction.txt +PD_MAJOR_VERSION := $(shell grep PD_MAJOR_VERSION m_pd.h | \ + sed 's|^.define *PD_MAJOR_VERSION *\([0-9]*\).*|\1|' ) +PD_MINOR_VERSION := $(shell grep PD_MINOR_VERSION m_pd.h | \ + sed 's|^.define *PD_MINOR_VERSION *\([0-9]*\).*|\1|' ) +PD_BUGFIX_VERSION := $(shell grep PD_BUGFIX_VERSION m_pd.h | \ + sed 's|^.define *PD_BUGFIX_VERSION *\([0-9]*\).*|\1|' ) +PD_TEST_VERSION := $(shell grep PD_TEST_VERSION m_pd.h | \ + sed 's|^.define *PD_TEST_VERSION *"\(.*\)".*|\1|' ) +PD_VERSION := $(PD_MAJOR_VERSION).$(PD_MINOR_VERSION).$(PD_BUGFIX_VERSION) +ifneq ($(PD_TEST_VERSION),) + PD_VERSION := $(PD_VERSION)-$(PD_TEST_VERSION) +endif + + +# +# ------------------ targets ------------------------------------ +# + +.PHONY: all install clean testbin + +all: $(PDDLL) $(PDEXEC) $(PDSEND) $(PDRECEIVE) $(PDCOM) + +$(OBJ) : %.o : %.c + $(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c + +$(GOBJ) : %.o : %.c + $(CC) $(CFLAGS) $(GFLAGS) $(GINCLUDE) -c -o $*.o $*.c + +$(SROBJ) : %.o : %.c + $(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c + +$(PAOBJ) : %.o : %.c + $(CC) $(CFLAGS) $(GFLAGS) $(INCPA) -c -o $*.o $*.c + +$(ASIOOBJ) : %.o : %.cpp + $(CXX) $(CFLAGS) $(INCPA) -c -o $*.o $*.cpp + +$(PMOBJ) : %.o : %.c + $(CC) $(CFLAGS) $(GFLAGS) $(PMINCLUDE) -c -o $*.o $*.c + +$(VOBJ) : %.o : %.c + $(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c + +$(PDSEND): u_pdsend.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $(PDSEND) u_pdsend.o $(LIBS) + $(STRIP) $(PDSEND) + +$(PDRECEIVE): u_pdreceive.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $(PDRECEIVE) u_pdreceive.o $(LIBS) + $(STRIP) $(PDRECEIVE) + +$(PDEXEC): s_entry.o pd.res + $(CXX) $(LDFLAGS) -mwindows -o $(PDEXEC) s_entry.o pd.res $(LIBS) pd.a + $(STRIP) -s $(PDEXEC) + +$(PDCOM): s_entry.o + $(CXX) $(LDFLAGS) -o $(PDCOM) s_entry.o $(LIBS) pd.a + $(STRIP) -s $(PDCOM) + +$(PDDLL): $(OBJC) + $(CXX) -shared $(LDFLAGS) -o $(PDDLL) $(OBJC) $(LIBS) \ + -Wl,--export-all-symbols -Wl,--out-implib=pd.a; + $(STRIP) $(PDDLL) + +pd.res: pd.rc + $(WINDRES) pd.rc -O coff -o pd.res + +../bin/pdstatic.exe: $(OBJC) + $(CXX) -static \ + $(LDFLAGS) -o ../bin/pdstatic.exe $(OBJC) \ + $(LIBS) -lole32 -static-libgcc -static-libstdc++ + $(STRIP) -s ../bin/pdstatic.exe + +#vstschedlib.dll: $(VOBJ) +# $(DLLWRAP) --export-all-symbols --output-def vst.def \ +# --output-lib=vst.a --dllname=vstschedlib.dll s_audio_vst.o pd.a $(LIBS) + +externs: + make -C ../extra all + +# kludge to put stuff into the pd/bin dir for testing +testbin: $(PDEXEC) $(PDDLL) $(PDCOM) + echo "Copying files to $(BIN_DIR)" + install -d $(BIN_DIR) + install -p $(PDDLL) $(BIN_DIR) + install -p pd.ico $(BIN_DIR) + install -p $(PDCOM) $(BIN_DIR) + install -p $(PDEXEC) $(BIN_DIR) + +ABOUT_FILE=$(DESTDIR)$(pddocdir)/1.manual/1.introduction.txt +install: all +# locales +# make libpddir=$(libpddir) -C ../po install +# install extra stuff +# make libpddir=$(libpddir) -C ../extra install +# the real install + install -d $(DESTDIR)$(bindir) + install -p ../tcl/*.tcl $(DESTDIR)$(bindir)/ + install -p $(PDEXEC) $(DESTDIR)$(bindir)/$(PDEXEC) + install -p $(PDCOM) $(DESTDIR)$(bindir)/$(PDCOM) + install -p pd.dll $(DESTDIR)$(bindir)/pd.dll + install -p pd.ico $(DESTDIR)$(bindir)/pd.ico + install -p $(PDSEND) $(DESTDIR)$(bindir)/$(PDSEND) + install -p $(PDRECEIVE) $(DESTDIR)$(bindir)/$(PDRECEIVE) + for dir in $(shell ls -1 ../doc | grep -v CVS); do \ + echo "installing $$dir"; \ + install -d $(DESTDIR)$(pddocdir)/$$dir ; \ + install -p ../doc/$$dir/*.* $(DESTDIR)$(pddocdir)/$$dir ; \ + done + for dir in $(shell ls -1 ../doc/7.stuff | grep -v CVS); do \ + echo "installing 7.stuff/$$dir"; \ + install -d $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \ + install -p ../doc/7.stuff/$$dir/*.* $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \ + done + mv $(ABOUT_FILE) $(ABOUT_FILE).tmp + cat $(ABOUT_FILE).tmp | sed 's|PD_VERSION|Pd version $(PD_VERSION)|' \ + > $(ABOUT_FILE) + rm $(ABOUT_FILE).tmp + install -d $(DESTDIR)$(libpddir)/extra +# install -p $(pd_src)/extra/*/*.dll $(DESTDIR)$(libpddir)/extra + install -p $(pd_src)/extra/*.pd $(DESTDIR)$(libpddir)/extra + install -d $(DESTDIR)$(pddocdir)/5.reference + install -p ../extra/*/*.pd $(DESTDIR)$(pddocdir)/5.reference + install -p ../extra/*-help.pd $(DESTDIR)$(pddocdir)/5.reference + install -d $(DESTDIR)$(includedir) + install -p m_pd.h $(DESTDIR)$(includedir)/m_pd.h + install -p s_stuff.h $(DESTDIR)$(includedir)/s_stuff.h + @echo "Pd install succeeded." + + +clean: + -rm -f -- $(BIN_DIR)/*.* + -rm -f -- *.o *.a *.def + -rm -f -- pd*.exe pd*.dll $(PDCOM) + -rm -f -- $(OBJ) $(GOBJ) $(SROBJ) $(PAOBJ) $(ASIOOBJ) $(PMOBJ) + -rm -f -- $(pd_src)/extra/*/*.dll $(pd_src)/extra/*/*.o + -rm -f makefile.dependencies + +distclean: clean + rm -rf -- config.cache config.log config.status makefile tags \ + autom4te-*.cache + +tags: $(SRC) $(GSRC); ctags *.[ch] + +depend: makefile.dependencies + +makefile.dependencies: $(SRC) $(PASRC) $(HEADERS) + $(CC) $(INCLUDE) $(INCPA) $(CFLAGS) -M $(SRC) $(PASRC) $(HEADERS) \ + > makefile.dependencies + +uninstall: + -rm $(prefix)/bin/pd*.exe + -rm $(prefix)/bin/pd*.com + -rm $(prefix)/bin/pd*.dll + -rm $(prefix)/bin/*.tcl + + +test_locations: + @echo "PD_VERSION: $(PD_VERSION)" + @echo "PACKAGE_VERSION: $(PACKAGE_VERSION)" + @echo "CWD $(CWD)" + @echo "DESTDIR $(DESTDIR)" + @echo "PREFIX $(prefix)" + @echo "BINDIR $(bindir)" + @echo "LIBDIR $(libdir)" + @echo "OBJECTSDIR $(objectsdir)" + @echo "PDDOCDIR $(pddocdir)" + @echo "LIBPDDIR $(libpddir)" + @echo "LIBPDBINDIR $(libpdbindir)" + @echo "HELPDIR $(helpdir)" + @echo "MANUALSDIR $(manualsdir)" + @echo "EXAMPLESDIR $(examplesdir)" + + +include makefile.dependencies diff --git a/ports/camomile/source/LibPd/pure-data/src/makefile.msvc b/ports/camomile/source/LibPd/pure-data/src/makefile.msvc new file mode 100644 index 00000000..85e2843a --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/makefile.msvc @@ -0,0 +1,220 @@ +# Makefile for PD using Microsoft Visual C/C++ (MSVC) -- note defines +# which will have to be adapted to whichever specific version of MSVC you +# have lying around. + +MSCC = cl +MSLN = link +COPY = copy +DELETE = del + +VCSDK = "C:/Program Files/Microsoft SDKs/Windows/v6.0A" +VC9 = "C:/Program Files/Microsoft Visual Studio 9.0/VC" + +WISH = wish85.exe + +EXTRA_LIBPATH= +EXTRA_INCLUDES= +## the following adds the search paths for compiler/linker +## if the build system hasn't been properly setup by calling +## the 'vcvarsall.bat' (MSVC) resp. 'SetEnv.bat' (MSSDK) scripts. +## the logic checks whether some variables are set/unset + +## the code is a bit convoluted because we want it to work +## with both 'GNU make' and 'nmake' +## see https://stackoverflow.com/a/30906085/1169096 + +# \ +!ifndef 0 # \ +# nmake code here \ +!IFNDEF VCINSTALLDIR # \ +VCINSTALLDIR = $(VC9) # \ +EXTRA_INCLUDES = /I$(VC9)/Include $(EXTRA_INCLUDES) # \ +EXTRA_LIBPATH = /LIBPATH:$(VC9)/lib $(EXTRA_LIBPATH) # \ +!ENDIF # \ +!IFNDEF WINDOWSSDKDIR # \ +WINDOWSSDKDIR = $(VCSDK) # \ +EXTRA_INCLUDES = /I$(VCSDK)/Include $(EXTRA_INCLUDES) # \ +EXTRA_LIBPATH = /LIBPATH:$(VCSDK)/lib $(EXTRA_LIBPATH)# \ +!ENDIF # \ +!else +# GNU make code here +ifndef VCINSTALLDIR +VCINSTALLDIR = $(VC9) +EXTRA_INCLUDES += /I$(VC9)/Include +EXTRA_LIBPATH += /LIBPATH:$(VC9)/lib +endif +ifndef WINDOWSSDKDIR +WINDOWSSDKDIR = $(VCSDK) +EXTRA_INCLUDES += /I$(VCSDK)/Include +EXTRA_LIBPATH += /LIBPATH:$(VCSDK)/lib +endif +# \ +!endif + +PDINCLUDE = /I./ $(EXTRA_INCLUDES) + +PDLIB = /NODEFAULTLIB:libcmt /NODEFAULTLIB:libcpmt /NODEFAULTLIB:oldnames \ + /NODEFAULTLIB:libc /NODEFAULTLIB:uuid /NODEFAULTLIB:ole32 \ + $(EXTRA_LIBPATH) \ + kernel32.lib \ + wsock32.lib winmm.lib \ + advapi32.lib setupapi.lib \ + ../bin/pthreadVC.lib \ + libcmt.lib oldnames.lib + +AFLAGS = /D__i386__ +# MSW, NT: legacy defines of Pd +# WIN32: portmidi, portaudio +# WINDOWS: portaudio +# _WINDOWS: unused! +CFLAGS = /nologo \ + /W3 /Ox $(AFLAGS) \ + /DMSW /DNT /DWIN32 /DWINDOWS /D_WINDOWS \ + /DWISH=\"$(WISH)\" \ + /DPD /DPD_INTERNAL \ + /DUSEAPI_MMIO /DUSEAPI_PORTAUDIO \ + /DPA_LITTLE_ENDIAN /DPA19 \ + /D_CRT_SECURE_NO_WARNINGS +LFLAGS = /nologo + +SYSSRC = s_audio_pa.c s_audio_paring.c \ + s_audio_mmio.c s_midi_pm.c + +SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \ + g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c g_clone.c \ + g_all_guis.c g_bang.c g_hdial.c g_hslider.c g_mycanvas.c g_numbox.c \ + g_toggle.c g_vdial.c g_vslider.c g_vumeter.c \ + m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \ + m_conf.c m_glob.c m_sched.c \ + s_main.c s_inter.c s_file.c s_print.c \ + s_loader.c s_path.c s_entry.c s_audio.c s_midi.c s_utf8.c \ + d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \ + d_math.c d_fft.c d_fft_fftsg.c d_array.c d_global.c \ + d_delay.c d_resample.c d_soundfile.c \ + x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \ + x_time.c x_acoustics.c x_net.c x_text.c x_gui.c x_list.c x_array.c \ + x_scalar.c x_vexp.c x_vexp_if.c x_vexp_fun.c \ + $(SYSSRC) + +PADIR = ../portaudio/portaudio +INCPA = -I$(PADIR)/include -I$(PADIR)/src/common -I$(PADIR)/src/os/win +PASRC = $(PADIR)/src + +PAOBJ = pa_stream.obj pa_trace.obj pa_process.obj \ + pa_front.obj pa_dither.obj pa_cpuload.obj pa_converters.obj \ + pa_allocation.obj pa_ringbuffer.obj \ + pa_win_hostapis.obj pa_win_util.obj pa_win_waveformat.obj \ + pa_win_wmme.obj +# pa_win_wdmks.obj + +PMDIR = ../portmidi/portmidi +INCPM = -I$(PMDIR)/pm_common -I$(PMDIR)/pm_win -I$(PMDIR)/porttime -DNEWBUFFER +SRCPM = $(PADIR)/pm_common/portmidi.c \ + $(PMDIR)/pm_common/pmutil.c \ + $(PMDIR)/porttime/porttime.c \ + $(PMDIR)/porttime/ptwinmm.c \ + $(PMDIR)/pm_win/pmwin.c \ + $(PMDIR)/pm_win/pmwinmm.c + +PMOBJ = portmidi.obj pmutil.obj porttime.obj ptwinmm.obj pmwin.obj pmwinmm.obj + +OBJC = $(SRC:.c=.obj) $(PAOBJ) $(PMOBJ) + +GSRC = t_main.c t_tkcmd.c + +GOBJ = $(GSRC:.c=.obj) + +ALLCF = $(CFLAGS) $(PDINCLUDE) $(INCPA) $(INCPM) + +.SUFFIXES: .obj +.c.obj: + $(MSCC) /c $(ALLCF) /Tc$*.c + +all: pd ../bin/pdsend.exe ../bin/pdreceive.exe + +.PHONY: pd + +pd: ../bin/pd.exe ../bin/pd.com + +../bin/pd.exe: s_entry.obj ../bin/pd.lib + $(MSLN) $(LFLAGS) /OUT:../bin/pd.exe /INCREMENTAL:NO s_entry.obj \ + ../bin/pd.lib $(PDLIB) + +../bin/pd.dll ../bin/pd.lib: $(OBJC) + $(MSLN) /DLL /OUT:../bin/pd.dll /EXPORT:sys_main $(LFLAGS) $(OBJC) \ + $(PDLIB) + +../bin/pdsend.exe: u_pdsend.obj + $(MSLN) $(LFLAGS) /out:../bin/pdsend.exe /INCREMENTAL:NO \ + u_pdsend.obj $(PDLIB) + +../bin/pdreceive.exe: u_pdreceive.obj + $(MSLN) $(LFLAGS) /out:../bin/pdreceive.exe /INCREMENTAL:NO \ + u_pdreceive.obj $(PDLIB) + +../bin/pd.com: s_entry_com.obj ../bin/pd.lib + $(MSLN) $(LFLAGS) /out:../bin/pd.com /INCREMENTAL:NO s_entry_com.obj \ + ../bin/pd.lib $(PDLIB) + +s_entry_com.obj: s_entry.c + $(COPY) s_entry.c s_entry_com.c + $(MSCC) /c -DCOMMANDVERSION s_entry_com.c + $(DELETE) s_entry_com.c + +PAAPI = -DPA_USE_WMME +PACF= $(PAAPI) $(ALLCF) +# explicit rules to compile portaudio sources: +pa_stream.obj: $(PASRC)/common/pa_stream.c + $(MSCC) /c $(PACF) $(PASRC)/common/pa_stream.c +pa_trace.obj: $(PASRC)/common/pa_trace.c + $(MSCC) /c $(PACF) $(PASRC)/common/pa_trace.c +pa_process.obj: $(PASRC)/common/pa_process.c + $(MSCC) /c $(PACF) $(PASRC)/common/pa_process.c +pa_front.obj: $(PASRC)/common/pa_front.c + $(MSCC) /c $(PACF) $(PASRC)/common/pa_front.c +pa_dither.obj: $(PASRC)/common/pa_dither.c + $(MSCC) /c $(PACF) $(PASRC)/common/pa_dither.c +pa_cpuload.obj: $(PASRC)/common/pa_cpuload.c + $(MSCC) /c $(PACF) $(PASRC)/common/pa_cpuload.c +pa_converters.obj: $(PASRC)/common/pa_converters.c + $(MSCC) /c $(PACF) $(PASRC)/common/pa_converters.c +pa_allocation.obj: $(PASRC)/common/pa_allocation.c + $(MSCC) /c $(PACF) $(PASRC)/common/pa_allocation.c +pa_ringbuffer.obj: $(PASRC)/common/pa_ringbuffer.c + $(MSCC) /c $(PACF) $(PASRC)/common/pa_ringbuffer.c + +pa_win_hostapis.obj: $(PASRC)/os/win/pa_win_hostapis.c + $(MSCC) /c $(PACF) $(PASRC)/os/win/pa_win_hostapis.c +pa_win_util.obj: $(PASRC)/os/win/pa_win_util.c + $(MSCC) /c $(PACF) $(PASRC)/os/win/pa_win_util.c +pa_win_waveformat.obj: $(PASRC)/os/win/pa_win_waveformat.c + $(MSCC) /c $(PACF) $(PASRC)/os/win/pa_win_waveformat.c +pa_win_coinitialize.obj: $(PASRC)/os/win/pa_win_coinitialize.c + $(MSCC) /c $(PACF) $(PASRC)/os/win/pa_win_coinitialize.c +pa_win_wmme.obj: $(PASRC)/hostapi/wmme/pa_win_wmme.c + $(MSCC) /c $(PACF) $(PASRC)/hostapi/wmme/pa_win_wmme.c +pa_win_wdmks.obj: $(PADIR)/a_win_wdmks/pa_win_wdmks.c + $(MSCC) /c $(PACF) \ + -DWINVER=0x400 -DKSAUDIO_SPEAKER_DIRECTOUT \ + $(PADIR)/pa_win_wdmks/pa_win_wdmks.c +pa_asio.obj: $(PASRC)/hostapi/asio/pa_asio.cpp + $(MSCC) /c $(PACF) $(PASRC)/hostapi/asio/pa_asio.cpp + +portmidi.obj: $(PMDIR)/pm_common/portmidi.c + $(MSCC) /c $(PACF) $(PMDIR)/pm_common/portmidi.c +pmutil.obj: $(PMDIR)/pm_common/pmutil.c + $(MSCC) /c $(PACF) $(PMDIR)/pm_common/pmutil.c +pmwin.obj: $(PMDIR)/pm_win/pmwin.c + $(MSCC) /c $(PACF) $(PMDIR)/pm_win/pmwin.c +pmwinmm.obj: $(PMDIR)/pm_win/pmwinmm.c + $(MSCC) /c $(PACF) $(PMDIR)/pm_win/pmwinmm.c +porttime.obj: $(PMDIR)/porttime/porttime.c + $(MSCC) /c $(PACF) $(PMDIR)/porttime/porttime.c +ptwinmm.obj: $(PMDIR)/porttime/ptwinmm.c + $(MSCC) /c $(PACF) $(PMDIR)/porttime/ptwinmm.c + +# the following should also clean up "bin" but it doesn't because "bin" holds +# precious stuff from elsewhere (luckily, our stuff matches 'pd*') +clean: + $(DELETE) *.obj + $(DELETE) ../bin/pd*.* diff --git a/ports/camomile/source/LibPd/pure-data/src/notes.txt b/ports/camomile/source/LibPd/pure-data/src/notes.txt new file mode 100644 index 00000000..42adf8dd --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/notes.txt @@ -0,0 +1,142 @@ +---------------- dolist -------------------- + +GUIs: slider, etc "clip (pre-0.46) " (on for old ones, off by default) +toggle to get "track value (pre-0.46)" + +x_text.c: +text dimension setting (message or creation arg - how to do it in structs?) +copying ala text_define_topointer +"open" and "save as" messages to open text window +how to integrate message boxes !? + +x_array.c: +allow for lying about x and y labels +no-mouse, quantize and clip flags for plotting/mousing +save ticks, labels, other flags (and add dialog to set them) +array y range to reflect y increment sign (so no 1 to -1 range) +array search and array sort objects +maybe: array segment, array spline, array sinesum, etc? or array gen? or +array forward (forwards message to defining array) +Is there a way to generate a pointer to an anonymous array? (do we need that?) + +OS specific: +linux: + rpm packages; BSD versions (set up VMs for testing) +windows: + put call to PA_Terminate back in where appropriate (first test on windows) + "-audiodev" with no args in registry can't start up? + mmio out of portaudio but consider adding wdmks +mac: + check if window titles wrong on Macintosh + clicking on windows seems sometimes not to open them + compile for jack on OSX by default (32 bit version at least). + turn on paMacCore_ChangeDeviceParameters for mac (pa_mac_core.h) + +problems: +fix behavior when dragging object outside screen (stop the evil auto-scrolls) +pd~ "start" followed by messages gives race condition because of "fromgui" biz +pd~ deadlock protection +find asdf$1 (e.g.) doesn't work +objects on GOP don't erase if you edit the GOP while they're showing +add -stack option to make 'regular' stack larger +menu item to save help patches to directory +look again at array vis/invis conundrum, g_template.c +floor, ciel functions in expr misdeclared +graph names don't appear until graph moved? (invis/vis on new array/rename) +don't filter locked click() through getrect +patcher inlets don't deal with scalars (zbug.pd) +read xx.txt in "bad" gives warnings +Krzysztof's qlist_next reentrancy bug +don't draw in/outlets on gui objects in graph-on-parent +get rid of messages causing renaming; try to prevent patches closing themselves. +scofo reports error on reading score1.txt +better error message for adc~ / dac~ reblocking +fix limitations in number of array elements that can be graphed + +more demonstration patches: +vibrato using variable delay +real-time spectrum grapher +document ||, |, etc, better + +features: +-nomidibuf flag (Nicola Pandini on pd list Aug 8 2013) +add way to query readsf~ for fill pointer (sf feature request 3598776) +'route' object to sprout inlet if no args (like sel) +optionally suppress leading "." directories and files on "open" +"installation mode": flag or messages to suppress menus&accelerators, + and invisibilize Pd window +sigmund~: sort by pitch; pitch estimate to include pitch height; message + to lie about previous track output +expr to parse exponential notation +mem alignment for SSE +replace gatom_escapit with a quoting mechanism (handle '[', spaces, etc.) +poly inlet to turn stealing on/off, plus mode to handle note-with-duration +integrate video into tilde objects +think of a way to embed abstractions in a patch (zlib?) +delete-in-rectangle message to Pds +put serial object in main dist (see rat@telecoma, Apr. 25; winfried May 22) +see x_list.c for more "list" object ideas +open64() for linux (if 32 bits, close soundfile and open64 it) + +paths: +fix declare to update current patch when changed +open_via_path call in d_soundfile.c isn't threadsafe +open/save panel to take messages to set extent list +new open_via_path to take list of extents + +editing: +control-enter to deselect an object? +pasting should look at current mouse location +clickless connection (hit 'c' key? see Bouchard paper) +tab to jump to a connected object (first one?) (shift-tab to back up?) +arrow keys to shift connections left and right +menu item to connect selected objects +highlight connections (and I/Os) on mouse motion +select line and hit "insert" to interpolate an object +option-drag an outlet to make a new, connected object +make a way to make multiple connections +"fix width" menu item +close-subwindows menu item +canvas zooming (use tcl/tk canvas scale command?) + +data: +add -x [-n?] flag to drawnumbers +flag to disable edits for arrays +make a 2-pass process for finding hot spot closest to any given click +hooks for table mousing, other changes (scalars?) +data to save as succession of "list" messages that textfile can store, etc. +data copy/paste doesn't check templates aren't changed +pointer == and select equivalents +cursor to show (x, y) location and/or what parameter is being set to what +improve typing at drawnumbers +append doesn't do symbols yet. +non-clickable arrays (plus arrays that respond more easily than default) +set -any, get -any +build out scalar object - naming; "scalar set/get" objects +pointer methods to search and delete +optimize by pre-fetching field name offsets in accessor objects +double-click on drawtext in scalar to create editor window + +more features: +signal inlets to sense signals; fix +~ etc, vcf~, biquad~, other filters +message dialog not to disappear +show results of opening MIDI on dialog +new: abs~, nexttick~, extend threshold~ and snapshot~ (vthreshold~ etc) +netsend separate thread +in glist_delete, consider why this can't be just "vis 0" -- why do we need it? +closebang and initbang +put in something for tilde order forcing +extensible "toolbar" so people can add external GUI objects +number boxes to darken for typing and/or received messages +new message box look +dialog to give values of $1, ... for the canvas +bang at end of line~, tabwrite~, etc. +should sys_bail kill all "threads" on the way out? +allow backslashes (or else really disallow them) +icon & desktop integration +tools (reassigns meaning of primary click) + +code style improvements: +-Wno-unused to -Wno-unused-paramter and clean up unused automatic variables +rewrite t_getbytes properly (m_newmemory.c in pd/attic) +obj_new should do a longjmp on out-of-memory diff --git a/ports/camomile/source/LibPd/pure-data/src/pd.ico b/ports/camomile/source/LibPd/pure-data/src/pd.ico new file mode 100644 index 00000000..2da5c243 Binary files /dev/null and b/ports/camomile/source/LibPd/pure-data/src/pd.ico differ diff --git a/ports/camomile/source/LibPd/pure-data/src/pd.rc b/ports/camomile/source/LibPd/pure-data/src/pd.rc new file mode 100644 index 00000000..32392603 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/pd.rc @@ -0,0 +1,25 @@ +id ICON "pd.ico" +1 VERSIONINFO +FILEVERSION 0,48,1,0 +PRODUCTVERSION 0,48,1,0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "puredata.info" + VALUE "FileDescription", "Pure Data Application" + VALUE "FileVersion", "0.48-1" + VALUE "InternalName", "pd.exe" + VALUE "LegalCopyright", "Miller Puckette, et al." + VALUE "OriginalFilename", "pd.exe" + VALUE "ProductName", "Pure Data" + VALUE "ProductVersion", "0.48-1" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/ports/camomile/source/LibPd/pure-data/src/s_audio.c b/ports/camomile/source/LibPd/pure-data/src/s_audio.c new file mode 100644 index 00000000..902212c9 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_audio.c @@ -0,0 +1,1134 @@ +/* Copyright (c) 2003, Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* machine-independent (well, mostly!) audio layer. Stores and recalls + audio settings from argparse routine and from dialog window. +*/ + +#include "m_pd.h" +#include "s_stuff.h" +#include +#ifdef _WIN32 +#include +#else +#include +#include +#include +#endif /* _WIN32 */ +#include +#include +#include + +#define SYS_DEFAULTCH 2 +typedef long t_pa_sample; +#define SYS_SAMPLEWIDTH sizeof(t_pa_sample) +#define SYS_BYTESPERCHAN (DEFDACBLKSIZE * SYS_SAMPLEWIDTH) +#define SYS_XFERSAMPS (SYS_DEFAULTCH*DEFDACBLKSIZE) +#define SYS_XFERSIZE (SYS_SAMPLEWIDTH * SYS_XFERSAMPS) +#define MAXNDEV 20 +#define DEVDESCSIZE 1024 + +static void audio_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, int *cancallback, + int maxndev, int devdescsize); + + /* these are set in this file when opening audio, but then may be reduced, + even to zero, in the system dependent open_audio routines. */ +int sys_inchannels; +int sys_outchannels; +int sys_advance_samples; /* scheduler advance in samples */ +int sys_audioapi = API_DEFAULT; +int sys_audioapiopened = -1; /* save last API opened for later closing */ +static int sys_meters; /* true if we're metering */ +static t_sample sys_inmax; /* max input amplitude */ +static t_sample sys_outmax; /* max output amplitude */ + + /* exported variables */ +int sys_schedadvance; /* scheduler advance in microseconds */ + + /* the "state" is normally one if we're open and zero otherwise; + but if the state is one, we still haven't necessarily opened the + audio hardware; see audio_isopen() below. */ +static int audio_state; + + /* last requested parameters */ +static int audio_naudioindev = -1; +static int audio_audioindev[MAXAUDIOINDEV]; +static int audio_audiochindev[MAXAUDIOINDEV]; +static char audio_indevnames[MAXMIDIINDEV * DEVDESCSIZE]; +static int audio_naudiooutdev = -1; +static int audio_audiooutdev[MAXAUDIOOUTDEV]; +static int audio_audiochoutdev[MAXAUDIOOUTDEV]; +static char audio_outdevnames[MAXMIDIINDEV * DEVDESCSIZE]; +static int audio_rate; +static int audio_advance = -1; +static int audio_callback; +static int audio_blocksize; + +static int audio_callback_is_open; /* reflects true actual state */ +static int audio_nextinchans, audio_nextoutchans; +void sched_audio_callbackfn(void); +void sched_reopenmeplease(void); + +int audio_isopen(void) +{ + return (audio_state && + ((audio_naudioindev > 0 && audio_audiochindev[0] > 0) + || (audio_naudiooutdev > 0 && audio_audiochoutdev[0] > 0))); +} + +void sys_get_audio_params( + int *pnaudioindev, int *paudioindev, int *chindev, + int *pnaudiooutdev, int *paudiooutdev, int *choutdev, + int *prate, int *padvance, int *pcallback, int *pblocksize) +{ + int i, devn; + *pnaudioindev = audio_naudioindev; + for (i = 0; i < audio_naudioindev; i++) + { + if ((devn = sys_audiodevnametonumber(0, + &audio_indevnames[i * DEVDESCSIZE])) >= 0) + paudioindev[i] = devn; + else paudioindev[i] = audio_audioindev[i]; + chindev[i] = audio_audiochindev[i]; + } + *pnaudiooutdev = audio_naudiooutdev; + for (i = 0; i < audio_naudiooutdev; i++) + { + if ((devn = sys_audiodevnametonumber(1, + &audio_outdevnames[i * DEVDESCSIZE])) >= 0) + paudiooutdev[i] = devn; + else paudiooutdev[i] = audio_audiooutdev[i]; + choutdev[i] = audio_audiochoutdev[i]; + } + *prate = audio_rate; + *padvance = audio_advance; + *pcallback = audio_callback; + *pblocksize = audio_blocksize; +} + +void sys_save_audio_params( + int naudioindev, int *audioindev, int *chindev, + int naudiooutdev, int *audiooutdev, int *choutdev, + int rate, int advance, int callback, int blocksize) +{ + int i; + audio_naudioindev = naudioindev; + for (i = 0; i < naudioindev; i++) + { + audio_audioindev[i] = audioindev[i], + audio_audiochindev[i] = chindev[i]; + sys_audiodevnumbertoname(0, audioindev[i], + &audio_indevnames[i * DEVDESCSIZE], DEVDESCSIZE); + } + audio_naudiooutdev = naudiooutdev; + for (i = 0; i < naudiooutdev; i++) + { + audio_audiooutdev[i] = audiooutdev[i], + audio_audiochoutdev[i] = choutdev[i]; + sys_audiodevnumbertoname(1, audiooutdev[i], + &audio_outdevnames[i * DEVDESCSIZE], DEVDESCSIZE); + } + audio_rate = rate; + audio_advance = advance; + audio_callback = callback; + audio_blocksize = blocksize; +} + + /* init routines for any API which needs to set stuff up before + any other API gets used. This is only true of OSS so far. */ +#ifdef USEAPI_OSS +void oss_init(void); +#endif + +static void audio_init( void) +{ + static int initted = 0; + if (initted) + return; + initted = 1; +#ifdef USEAPI_OSS + oss_init(); +#endif +} + + /* set channels and sample rate. */ + +void sys_setchsr(int chin, int chout, int sr) +{ + int nblk; + int inbytes = (chin ? chin : 2) * + (DEFDACBLKSIZE*sizeof(t_sample)); + int outbytes = (chout ? chout : 2) * + (DEFDACBLKSIZE*sizeof(t_sample)); + + if (STUFF->st_soundin) + freebytes(STUFF->st_soundin, + (STUFF->st_inchannels? STUFF->st_inchannels : 2) * + (DEFDACBLKSIZE*sizeof(t_sample))); + if (STUFF->st_soundout) + freebytes(STUFF->st_soundout, + (STUFF->st_outchannels? STUFF->st_outchannels : 2) * + (DEFDACBLKSIZE*sizeof(t_sample))); + STUFF->st_inchannels = chin; + STUFF->st_outchannels = chout; + STUFF->st_dacsr = sr; + sys_advance_samples = (sys_schedadvance * STUFF->st_dacsr) / (1000000.); + if (sys_advance_samples < DEFDACBLKSIZE) + sys_advance_samples = DEFDACBLKSIZE; + + STUFF->st_soundin = (t_sample *)getbytes(inbytes); + memset(STUFF->st_soundin, 0, inbytes); + + STUFF->st_soundout = (t_sample *)getbytes(outbytes); + memset(STUFF->st_soundout, 0, outbytes); + + if (sys_verbose) + post("input channels = %d, output channels = %d", + STUFF->st_inchannels, STUFF->st_outchannels); + canvas_resume_dsp(canvas_suspend_dsp()); +} + +/* ----------------------- public routines ----------------------- */ + + /* set audio device settings (after cleaning up the specified device and + channel vectors). The audio devices are "zero based" (i.e. "0" means the + first one.) We can later re-open audio and/or show the settings on a + dialog window. */ + +void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate, int advance, int callback, int blocksize) +{ + int i, *ip; + int defaultchannels = SYS_DEFAULTCH; + int inchans, outchans, nrealindev, nrealoutdev; + int realindev[MAXAUDIOINDEV], realoutdev[MAXAUDIOOUTDEV]; + int realinchans[MAXAUDIOINDEV], realoutchans[MAXAUDIOOUTDEV]; + + char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE]; + int indevs = 0, outdevs = 0, canmulti = 0, cancallback = 0; + + /* initialize device-arrays */ + for(i=0; i= 1) + { + nchindev=1; + chindev[0] = defaultchannels; + naudioindev = 1; + audioindev[0] = DEFAULTAUDIODEV; + } + else naudioindev = nchindev = 0; + } + else + { + for (i = 0; i < MAXAUDIOINDEV; i++) + audioindev[i] = i; + naudioindev = nchindev; + } + } + else + { + if (nchindev == -1) + { + nchindev = naudioindev; + for (i = 0; i < naudioindev; i++) + chindev[i] = defaultchannels; + } + else if (nchindev > naudioindev) + { + for (i = naudioindev; i < nchindev; i++) + { + if (i == 0) + audioindev[0] = DEFAULTAUDIODEV; + else audioindev[i] = audioindev[i-1] + 1; + } + naudioindev = nchindev; + } + else if (nchindev < naudioindev) + { + for (i = nchindev; i < naudioindev; i++) + { + if (i == 0) + chindev[0] = defaultchannels; + else chindev[i] = chindev[i-1]; + } + naudioindev = nchindev; + } + } + + if (naudiooutdev == -1) + { /* not set */ + if (nchoutdev == -1) + { + if (outdevs >= 1) + { + nchoutdev=1; + choutdev[0]=defaultchannels; + naudiooutdev=1; + audiooutdev[0] = DEFAULTAUDIODEV; + } + else nchoutdev = naudiooutdev = 0; + } + else + { + for (i = 0; i < MAXAUDIOOUTDEV; i++) + audiooutdev[i] = i; + naudiooutdev = nchoutdev; + } + } + else + { + if (nchoutdev == -1) + { + nchoutdev = naudiooutdev; + for (i = 0; i < naudiooutdev; i++) + choutdev[i] = defaultchannels; + } + else if (nchoutdev > naudiooutdev) + { + for (i = naudiooutdev; i < nchoutdev; i++) + { + if (i == 0) + audiooutdev[0] = DEFAULTAUDIODEV; + else audiooutdev[i] = audiooutdev[i-1] + 1; + } + naudiooutdev = nchoutdev; + } + else if (nchoutdev < naudiooutdev) + { + for (i = nchoutdev; i < naudiooutdev; i++) + { + if (i == 0) + choutdev[0] = defaultchannels; + else choutdev[i] = choutdev[i-1]; + } + naudiooutdev = nchoutdev; + } + } + + /* count total number of input and output channels */ + for (i = nrealindev = inchans = 0; i < naudioindev; i++) + if (chindev[i] > 0) + { + realinchans[nrealindev] = chindev[i]; + realindev[nrealindev] = audioindev[i]; + inchans += chindev[i]; + nrealindev++; + } + for (i = nrealoutdev = outchans = 0; i < naudiooutdev; i++) + if (choutdev[i] > 0) + { + realoutchans[nrealoutdev] = choutdev[i]; + realoutdev[nrealoutdev] = audiooutdev[i]; + outchans += choutdev[i]; + nrealoutdev++; + } + sys_schedadvance = advance * 1000; + sys_log_error(ERR_NOTHING); + audio_nextinchans = inchans; + audio_nextoutchans = outchans; + sys_setchsr(audio_nextinchans, audio_nextoutchans, rate); + sys_save_audio_params(nrealindev, realindev, realinchans, + nrealoutdev, realoutdev, realoutchans, rate, advance, callback, + blocksize); +} + +void sys_close_audio(void) +{ + if (sys_externalschedlib) + { + return; + } + if (!audio_isopen()) + return; +#ifdef USEAPI_PORTAUDIO + if (sys_audioapiopened == API_PORTAUDIO) + pa_close_audio(); + else +#endif +#ifdef USEAPI_JACK + if (sys_audioapiopened == API_JACK) + jack_close_audio(); + else +#endif +#ifdef USEAPI_OSS + if (sys_audioapiopened == API_OSS) + oss_close_audio(); + else +#endif +#ifdef USEAPI_ALSA + if (sys_audioapiopened == API_ALSA) + alsa_close_audio(); + else +#endif +#ifdef USEAPI_MMIO + if (sys_audioapiopened == API_MMIO) + mmio_close_audio(); + else +#endif +#ifdef USEAPI_AUDIOUNIT + if (sys_audioapiopened == API_AUDIOUNIT) + audiounit_close_audio(); + else +#endif +#ifdef USEAPI_ESD + if (sys_audioapiopened == API_ESD) + esd_close_audio(); + else +#endif +#ifdef USEAPI_DUMMY + if (sys_audioapiopened == API_DUMMY) + dummy_close_audio(); + else +#endif + post("sys_close_audio: unknown API %d", sys_audioapiopened); + sys_inchannels = sys_outchannels = 0; + sys_audioapiopened = -1; + sched_set_using_audio(SCHED_AUDIO_NONE); + audio_state = 0; + audio_callback_is_open = 0; + + sys_vgui("set pd_whichapi 0\n"); +} + + /* open audio using whatever parameters were last used */ +void sys_reopen_audio( void) +{ + int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV]; + int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV]; + int rate, advance, callback, blocksize, outcome = 0; + sys_get_audio_params(&naudioindev, audioindev, chindev, + &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback, + &blocksize); + sys_setchsr(audio_nextinchans, audio_nextoutchans, rate); + if (!naudioindev && !naudiooutdev) + { + sched_set_using_audio(SCHED_AUDIO_NONE); + return; + } +#ifdef USEAPI_PORTAUDIO + if (sys_audioapi == API_PORTAUDIO) + { + int blksize = (audio_blocksize ? audio_blocksize : 64); + if (sys_verbose) + fprintf(stderr, "blksize %d, advance %d\n", blksize, sys_advance_samples/blksize); + outcome = pa_open_audio((naudioindev > 0 ? chindev[0] : 0), + (naudiooutdev > 0 ? choutdev[0] : 0), rate, STUFF->st_soundin, + STUFF->st_soundout, blksize, sys_advance_samples/blksize, + (naudioindev > 0 ? audioindev[0] : 0), + (naudiooutdev > 0 ? audiooutdev[0] : 0), + (callback ? sched_audio_callbackfn : 0)); + } + else +#endif +#ifdef USEAPI_JACK + if (sys_audioapi == API_JACK) + outcome = jack_open_audio((naudioindev > 0 ? chindev[0] : 0), + (naudiooutdev > 0 ? choutdev[0] : 0), rate, + (callback ? sched_audio_callbackfn : 0)); + + else +#endif +#ifdef USEAPI_OSS + if (sys_audioapi == API_OSS) + outcome = oss_open_audio(naudioindev, audioindev, naudioindev, + chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, + audio_blocksize); + else +#endif +#ifdef USEAPI_ALSA + /* for alsa, only one device is supported; it may + be open for both input and output. */ + if (sys_audioapi == API_ALSA) + outcome = alsa_open_audio(naudioindev, audioindev, naudioindev, + chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, + audio_blocksize); + else +#endif +#ifdef USEAPI_MMIO + if (sys_audioapi == API_MMIO) + outcome = mmio_open_audio(naudioindev, audioindev, naudioindev, + chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, + audio_blocksize); + else +#endif +#ifdef USEAPI_AUDIOUNIT + if (sys_audioapi == API_AUDIOUNIT) + outcome = audiounit_open_audio((naudioindev > 0 ? chindev[0] : 0), + (naudioindev > 0 ? choutdev[0] : 0), rate); + else +#endif +#ifdef USEAPI_ESD + if (sys_audioapi == API_ALSA) + outcome = esd_open_audio(naudioindev, audioindev, naudioindev, + chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate); + else +#endif +#ifdef USEAPI_DUMMY + if (sys_audioapi == API_DUMMY) + outcome = dummy_open_audio(naudioindev, naudiooutdev, rate); + else +#endif + if (sys_audioapi == API_NONE) + ; + else post("unknown audio API specified"); + if (outcome) /* failed */ + { + audio_state = 0; + sched_set_using_audio(SCHED_AUDIO_NONE); + sys_audioapiopened = -1; + audio_callback_is_open = 0; + } + else + { + /* fprintf(stderr, "started w/callback %d\n", callback); */ + audio_state = 1; + sched_set_using_audio( + (callback ? SCHED_AUDIO_CALLBACK : SCHED_AUDIO_POLL)); + sys_audioapiopened = sys_audioapi; + audio_callback_is_open = callback; + } + sys_vgui("set pd_whichapi %d\n", (outcome == 0 ? sys_audioapi : 0)); +} + +int sys_send_dacs(void) +{ + if (sys_meters) + { + int i, n; + t_sample maxsamp; + for (i = 0, n = sys_inchannels * DEFDACBLKSIZE, maxsamp = sys_inmax; + i < n; i++) + { + t_sample f = STUFF->st_soundin[i]; + if (f > maxsamp) maxsamp = f; + else if (-f > maxsamp) maxsamp = -f; + } + sys_inmax = maxsamp; + for (i = 0, n = STUFF->st_outchannels * DEFDACBLKSIZE, + maxsamp = sys_outmax; i < n; i++) + { + t_sample f = STUFF->st_soundout[i]; + if (f > maxsamp) maxsamp = f; + else if (-f > maxsamp) maxsamp = -f; + } + sys_outmax = maxsamp; + } + +#ifdef USEAPI_PORTAUDIO + if (sys_audioapi == API_PORTAUDIO) + return (pa_send_dacs()); + else +#endif +#ifdef USEAPI_JACK + if (sys_audioapi == API_JACK) + return (jack_send_dacs()); + else +#endif +#ifdef USEAPI_OSS + if (sys_audioapi == API_OSS) + return (oss_send_dacs()); + else +#endif +#ifdef USEAPI_ALSA + if (sys_audioapi == API_ALSA) + return (alsa_send_dacs()); + else +#endif +#ifdef USEAPI_MMIO + if (sys_audioapi == API_MMIO) + return (mmio_send_dacs()); + else +#endif +#ifdef USEAPI_AUDIOUNIT + if (sys_audioapi == API_AUDIOUNIT) + return (audiounit_send_dacs()); + else +#endif +#ifdef USEAPI_ESD + if (sys_audioapi == API_ESD) + return (esd_send_dacs()); + else +#endif +#ifdef USEAPI_DUMMY + if (sys_audioapi == API_DUMMY) + return (dummy_send_dacs()); + else +#endif + post("unknown API"); + return (0); +} + +t_float sys_getsr(void) +{ + return (STUFF->st_dacsr); +} + +int sys_get_outchannels(void) +{ + return (STUFF->st_outchannels); +} + +int sys_get_inchannels(void) +{ + return (STUFF->st_inchannels); +} + +void sys_getmeters(t_sample *inmax, t_sample *outmax) +{ + if (inmax) + { + sys_meters = 1; + *inmax = sys_inmax; + *outmax = sys_outmax; + } + else + sys_meters = 0; + sys_inmax = sys_outmax = 0; +} + +void sys_reportidle(void) +{ +} + +/* this could later be set by a preference but for now it seems OK to just +keep jack audio open but close unused audio devices for any other API */ +int audio_shouldkeepopen( void) +{ + return (sys_audioapi == API_JACK); +} + +static void audio_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, int *cancallback, + int maxndev, int devdescsize) +{ + audio_init(); + *cancallback = 0; /* may be overridden by specific API implementation */ +#ifdef USEAPI_PORTAUDIO + if (sys_audioapi == API_PORTAUDIO) + { + pa_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti, + maxndev, devdescsize); + *cancallback = 1; + } + else +#endif +#ifdef USEAPI_JACK + if (sys_audioapi == API_JACK) + { + jack_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti, + maxndev, devdescsize); + *cancallback = 1; + } + else +#endif +#ifdef USEAPI_OSS + if (sys_audioapi == API_OSS) + { + oss_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti, + maxndev, devdescsize); + } + else +#endif +#ifdef USEAPI_ALSA + if (sys_audioapi == API_ALSA) + { + alsa_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti, + maxndev, devdescsize); + } + else +#endif +#ifdef USEAPI_MMIO + if (sys_audioapi == API_MMIO) + { + mmio_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti, + maxndev, devdescsize); + } + else +#endif +#ifdef USEAPI_AUDIOUNIT + if (sys_audioapi == API_AUDIOUNIT) + { + } + else +#endif +#ifdef USEAPI_ESD + if (sys_audioapi == API_ESD) + { + esd_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti, + maxndev, devdescsize); + } + else +#endif +#ifdef USEAPI_DUMMY + if (sys_audioapi == API_DUMMY) + { + dummy_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti, + maxndev, devdescsize); + } + else +#endif + { + /* this shouldn't happen once all the above get filled in. */ + int i; + *nindevs = *noutdevs = 3; + for (i = 0; i < 3; i++) + { + sprintf(indevlist + i * devdescsize, "input device #%d", i+1); + sprintf(outdevlist + i * devdescsize, "output device #%d", i+1); + } + *canmulti = 0; + } +} + + +static void sys_listaudiodevs(void ) +{ + char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE]; + int nindevs = 0, noutdevs = 0, i, canmulti = 0, cancallback = 0; + + audio_getdevs(indevlist, &nindevs, outdevlist, &noutdevs, &canmulti, + &cancallback, MAXNDEV, DEVDESCSIZE); + + if (!nindevs) + post("no audio input devices found"); + else + { + /* To agree with command line flags, normally start at 1 */ + /* But microsoft "MMIO" device list starts at 0 (the "mapper"). */ + /* (see also sys_mmio variable in s_main.c) */ + + post("audio input devices:"); + for (i = 0; i < nindevs; i++) + post("%d. %s", i + (sys_audioapi != API_MMIO), + indevlist + i * DEVDESCSIZE); + } + if (!noutdevs) + post("no audio output devices found"); + else + { + post("audio output devices:"); + for (i = 0; i < noutdevs; i++) + post("%d. %s", i + (sys_audioapi != API_MMIO), + outdevlist + i * DEVDESCSIZE); + } + post("API number %d\n", sys_audioapi); +} + + + /* start an audio settings dialog window */ +void glob_audio_properties(t_pd *dummy, t_floatarg flongform) +{ + char buf[1024 + 2 * MAXNDEV*(DEVDESCSIZE+4)]; + /* these are the devices you're using: */ + int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV]; + int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV]; + int audioindev1, audioindev2, audioindev3, audioindev4, + audioinchan1, audioinchan2, audioinchan3, audioinchan4, + audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4, + audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4; + int rate, advance, callback, blocksize; + /* these are all the devices on your system: */ + char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE]; + int nindevs = 0, noutdevs = 0, canmulti = 0, cancallback = 0, i; + + audio_getdevs(indevlist, &nindevs, outdevlist, &noutdevs, &canmulti, + &cancallback, MAXNDEV, DEVDESCSIZE); + + sys_gui("global audio_indevlist; set audio_indevlist {}\n"); + for (i = 0; i < nindevs; i++) + sys_vgui("lappend audio_indevlist {%s}\n", + indevlist + i * DEVDESCSIZE); + + sys_gui("global audio_outdevlist; set audio_outdevlist {}\n"); + for (i = 0; i < noutdevs; i++) + sys_vgui("lappend audio_outdevlist {%s}\n", + outdevlist + i * DEVDESCSIZE); + + sys_get_audio_params(&naudioindev, audioindev, chindev, + &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback, + &blocksize); + + /* post("naudioindev %d naudiooutdev %d longform %f", + naudioindev, naudiooutdev, flongform); */ + if (naudioindev > 1 || naudiooutdev > 1) + flongform = 1; + + audioindev1 = (naudioindev > 0 && audioindev[0]>= 0 ? audioindev[0] : 0); + audioindev2 = (naudioindev > 1 && audioindev[1]>= 0 ? audioindev[1] : 0); + audioindev3 = (naudioindev > 2 && audioindev[2]>= 0 ? audioindev[2] : 0); + audioindev4 = (naudioindev > 3 && audioindev[3]>= 0 ? audioindev[3] : 0); + audioinchan1 = (naudioindev > 0 ? chindev[0] : 0); + audioinchan2 = (naudioindev > 1 ? chindev[1] : 0); + audioinchan3 = (naudioindev > 2 ? chindev[2] : 0); + audioinchan4 = (naudioindev > 3 ? chindev[3] : 0); + audiooutdev1 = (naudiooutdev > 0 && audiooutdev[0]>=0 ? audiooutdev[0] : 0); + audiooutdev2 = (naudiooutdev > 1 && audiooutdev[1]>=0 ? audiooutdev[1] : 0); + audiooutdev3 = (naudiooutdev > 2 && audiooutdev[2]>=0 ? audiooutdev[2] : 0); + audiooutdev4 = (naudiooutdev > 3 && audiooutdev[3]>=0 ? audiooutdev[3] : 0); + audiooutchan1 = (naudiooutdev > 0 ? choutdev[0] : 0); + audiooutchan2 = (naudiooutdev > 1 ? choutdev[1] : 0); + audiooutchan3 = (naudiooutdev > 2 ? choutdev[2] : 0); + audiooutchan4 = (naudiooutdev > 3 ? choutdev[3] : 0); + sprintf(buf, +"pdtk_audio_dialog %%s \ +%d %d %d %d %d %d %d %d \ +%d %d %d %d %d %d %d %d \ +%d %d %d %d %d %d\n", + audioindev1, audioindev2, audioindev3, audioindev4, + audioinchan1, audioinchan2, audioinchan3, audioinchan4, + audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4, + audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4, + rate, advance, canmulti, (cancallback ? callback : -1), + (flongform != 0), blocksize); + gfxstub_deleteforkey(0); + gfxstub_new(&glob_pdobject, (void *)glob_audio_properties, buf); +} + +extern int pa_foo; + /* new values from dialog window */ +void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) +{ + int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV]; + int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV]; + int rate, advance, audioon, i, nindev, noutdev; + int audioindev1, audioinchan1, audiooutdev1, audiooutchan1; + int newaudioindev[4], newaudioinchan[4], + newaudiooutdev[4], newaudiooutchan[4]; + /* the new values the dialog came back with: */ + int newrate = atom_getfloatarg(16, argc, argv); + int newadvance = atom_getfloatarg(17, argc, argv); + int newcallback = atom_getfloatarg(18, argc, argv); + int newblocksize = atom_getfloatarg(19, argc, argv); + + for (i = 0; i < 4; i++) + { + newaudioindev[i] = atom_getfloatarg(i, argc, argv); + newaudioinchan[i] = atom_getfloatarg(i+4, argc, argv); + newaudiooutdev[i] = atom_getfloatarg(i+8, argc, argv); + newaudiooutchan[i] = atom_getfloatarg(i+12, argc, argv); + } + + for (i = 0, nindev = 0; i < 4; i++) + { + if (newaudioinchan[i]) + { + newaudioindev[nindev] = newaudioindev[i]; + newaudioinchan[nindev] = newaudioinchan[i]; + /* post("in %d %d %d", nindev, + newaudioindev[nindev] , newaudioinchan[nindev]); */ + nindev++; + } + } + for (i = 0, noutdev = 0; i < 4; i++) + { + if (newaudiooutchan[i]) + { + newaudiooutdev[noutdev] = newaudiooutdev[i]; + newaudiooutchan[noutdev] = newaudiooutchan[i]; + /* post("out %d %d %d", noutdev, + newaudiooutdev[noutdev] , newaudioinchan[noutdev]); */ + noutdev++; + } + } + + sys_set_audio_settings_reopen(nindev, newaudioindev, nindev, newaudioinchan, + noutdev, newaudiooutdev, noutdev, newaudiooutchan, + newrate, newadvance, newcallback, newblocksize); +} + +void sys_set_audio_settings_reopen(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate, int advance, int callback, int newblocksize) +{ + if (callback < 0) + callback = 0; + if (newblocksize != (1< 2048) + newblocksize = DEFDACBLKSIZE; + + if (!audio_callback_is_open && !callback) + sys_close_audio(); + sys_set_audio_settings(naudioindev, audioindev, nchindev, chindev, + naudiooutdev, audiooutdev, nchoutdev, choutdev, + rate, advance, (callback >= 0 ? callback : 0), newblocksize); + if (!audio_callback_is_open && !callback) + sys_reopen_audio(); + else sched_reopenmeplease(); +} + +void sys_listdevs(void ) +{ +#ifdef USEAPI_PORTAUDIO + if (sys_audioapi == API_PORTAUDIO) + sys_listaudiodevs(); + else +#endif +#ifdef USEAPI_JACK + if (sys_audioapi == API_JACK) + jack_listdevs(); + else +#endif +#ifdef USEAPI_OSS + if (sys_audioapi == API_OSS) + sys_listaudiodevs(); + else +#endif +#ifdef USEAPI_ALSA + if (sys_audioapi == API_ALSA) + sys_listaudiodevs(); + else +#endif +#ifdef USEAPI_MMIO + if (sys_audioapi == API_MMIO) + sys_listaudiodevs(); + else +#endif +#ifdef USEAPI_AUDIOUNIT + if (sys_audioapi == API_AUDIOUNIT) + sys_listaudiodevs(); + else +#endif +#ifdef USEAPI_ESD + if (sys_audioapi == API_ESD) + sys_listaudiodevs(); + else +#endif +#ifdef USEAPI_DUMMY + if (sys_audioapi == API_DUMMY) + sys_listaudiodevs(); + else +#endif + post("unknown API"); + + sys_listmididevs(); +} + +void sys_get_audio_devs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, int *cancallback, + int maxndev, int devdescsize) +{ + audio_getdevs(indevlist, nindevs, + outdevlist, noutdevs, + canmulti, cancallback, + maxndev, devdescsize); +} + +void sys_set_audio_api(int which) +{ + int ok = 0; /* check if the API is actually compiled in */ +#ifdef USEAPI_PORTAUDIO + ok += (which == API_PORTAUDIO); +#endif +#ifdef USEAPI_JACK + ok += (which == API_JACK); +#endif +#ifdef USEAPI_OSS + ok += (which == API_OSS); +#endif +#ifdef USEAPI_ALSA + ok += (which == API_ALSA); +#endif +#ifdef USEAPI_MMIO + ok += (which == API_MMIO); +#endif +#ifdef USEAPI_AUDIOUNIT + ok += (which == API_AUDIOUNIT); +#endif +#ifdef USEAPI_ESD + ok += (which == API_ESD); +#endif +#ifdef USEAPI_DUMMY + ok += (which == API_DUMMY); +#endif + if (!which) + ok++; + if (!ok) + { + post("API %d not supported, reverting to %d (%s)", + which, API_DEFAULT, API_DEFSTRING); + which = API_DEFAULT; + } + sys_audioapi = which; + if (sys_verbose && ok) + post("sys_audioapi set to %d", sys_audioapi); +} + +void glob_audio_setapi(void *dummy, t_floatarg f) +{ + int newapi = f; + if (newapi) + { + if (newapi == sys_audioapi) + { + if (!audio_isopen() && audio_shouldkeepopen()) + sys_reopen_audio(); + } + else + { + sys_close_audio(); + sys_audioapi = newapi; + /* bash device params back to default */ + audio_naudioindev = audio_naudiooutdev = 1; + audio_audioindev[0] = audio_audiooutdev[0] = DEFAULTAUDIODEV; + audio_audiochindev[0] = audio_audiochoutdev[0] = SYS_DEFAULTCH; + sys_reopen_audio(); + } + glob_audio_properties(0, 0); + } + else if (audio_isopen()) + { + sys_close_audio(); + } +} + + /* start or stop the audio hardware */ +void sys_set_audio_state(int onoff) +{ + if (onoff) /* start */ + { + if (!audio_isopen()) + sys_reopen_audio(); + } + else + { + if (audio_isopen()) + sys_close_audio(); + } +} + +void sys_get_audio_apis(char *buf) +{ + int n = 0; + strcpy(buf, "{ "); +#ifdef USEAPI_OSS + sprintf(buf + strlen(buf), "{OSS %d} ", API_OSS); n++; +#endif +#ifdef USEAPI_MMIO + sprintf(buf + strlen(buf), "{\"standard (MMIO)\" %d} ", API_MMIO); n++; +#endif +#ifdef USEAPI_ALSA + sprintf(buf + strlen(buf), "{ALSA %d} ", API_ALSA); n++; +#endif +#ifdef USEAPI_PORTAUDIO +#ifdef _WIN32 + sprintf(buf + strlen(buf), + "{\"ASIO (via portaudio)\" %d} ", API_PORTAUDIO); +#else +#ifdef __APPLE__ + sprintf(buf + strlen(buf), + "{\"standard (portaudio)\" %d} ", API_PORTAUDIO); +#else + sprintf(buf + strlen(buf), "{portaudio %d} ", API_PORTAUDIO); +#endif +#endif + n++; +#endif +#ifdef USEAPI_JACK + sprintf(buf + strlen(buf), "{jack %d} ", API_JACK); n++; +#endif +#ifdef USEAPI_AUDIOUNIT + sprintf(buf + strlen(buf), "{AudioUnit %d} ", API_AUDIOUNIT); n++; +#endif +#ifdef USEAPI_ESD + sprintf(buf + strlen(buf), "{ESD %d} ", API_ESD); n++; +#endif +#ifdef USEAPI_DUMMY + sprintf(buf + strlen(buf), "{dummy %d} ", API_DUMMY); n++; +#endif + strcat(buf, "}"); + /* then again, if only one API (or none) we don't offer any choice. */ + if (n < 2) + strcpy(buf, "{}"); +} + +#ifdef USEAPI_ALSA +void alsa_putzeros(int n); +void alsa_getzeros(int n); +void alsa_printstate( void); +#endif + +/* convert a device name to a (1-based) device number. (Output device if +'output' parameter is true, otherwise input device). Negative on failure. */ + +int sys_audiodevnametonumber(int output, const char *name) +{ + char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE]; + int nindevs = 0, noutdevs = 0, i, canmulti, cancallback; + + sys_get_audio_devs(indevlist, &nindevs, outdevlist, &noutdevs, + &canmulti, &cancallback, MAXNDEV, DEVDESCSIZE); + + if (output) + { + for (i = 0; i < noutdevs; i++) + { + unsigned long comp = strlen(name); + if (comp > strlen(outdevlist + i * DEVDESCSIZE)) + comp = strlen(outdevlist + i * DEVDESCSIZE); + if (!strncmp(name, outdevlist + i * DEVDESCSIZE, comp)) + return (i); + } + } + else + { + for (i = 0; i < nindevs; i++) + { + unsigned long comp = strlen(name); + if (comp > strlen(indevlist + i * DEVDESCSIZE)) + comp = strlen(indevlist + i * DEVDESCSIZE); + if (!strncmp(name, indevlist + i * DEVDESCSIZE, comp)) + return (i); + } + } + return (-1); +} + +/* convert a (1-based) device number to a device name. (Output device if +'output' parameter is true, otherwise input device). Empty string on failure. +*/ + +void sys_audiodevnumbertoname(int output, int devno, char *name, int namesize) +{ + char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE]; + int nindevs = 0, noutdevs = 0, i, canmulti, cancallback; + if (devno < 0) + { + *name = 0; + return; + } + sys_get_audio_devs(indevlist, &nindevs, outdevlist, &noutdevs, + &canmulti, &cancallback, MAXNDEV, DEVDESCSIZE); + if (output && (devno < noutdevs)) + strncpy(name, outdevlist + devno * DEVDESCSIZE, namesize); + else if (!output && (devno < nindevs)) + strncpy(name, indevlist + devno * DEVDESCSIZE, namesize); + else *name = 0; + name[namesize-1] = 0; +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_audio_alsa.c b/ports/camomile/source/LibPd/pure-data/src/s_audio_alsa.c new file mode 100644 index 00000000..dbc5812a --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_audio_alsa.c @@ -0,0 +1,973 @@ +/* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler, +* Winfried Ritsch, Karl MacMillan, and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* this file inputs and outputs audio using the ALSA API available on linux. */ + +/* support for ALSA pcmv2 api by Karl MacMillan */ +/* support for ALSA MMAP noninterleaved by Winfried Ritsch, IEM */ + +#include + +#include "m_pd.h" +#include "s_stuff.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "s_audio_alsa.h" +#include + +/* Defines */ +#define DEBUG(x) x +#define DEBUG2(x) {x;} + +/* needed for alsa 0.9 compatibility: */ +#if (SND_LIB_MAJOR < 1) +#define ALSAAPI9 +#endif + +static void alsa_checkiosync( void); +static void alsa_numbertoname(int iodev, char *devname, int nchar); +static int alsa_jittermax; +#define ALSA_DEFJITTERMAX 3 + + /* don't assume we can turn all 31 bits when doing float-to-fix; + otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. */ +#define FMAX 0x7ffff000 +#define CLIP32(x) (((x)>FMAX)?FMAX:((x) < -FMAX)?-FMAX:(x)) + +static char *alsa_snd_buf; +static int alsa_snd_bufsize; +static int alsa_buf_samps; +static snd_pcm_status_t *alsa_status; +static int alsa_usemmap; + +t_alsa_dev alsa_indev[ALSA_MAXDEV]; +t_alsa_dev alsa_outdev[ALSA_MAXDEV]; +int alsa_nindev; +int alsa_noutdev; + +/* #define DEBUG_ALSA_XFER */ +#ifdef DEBUG_ALSA_XFER +static int xferno = 0; +static int callno = 0; +#endif + +/* report an error condition if an error was flagged in the argument "err". +"fn" is 0 for input, 1 for output, otherwise N/A. "why" indicates where +in the code the error was hit. */ +static void check_error(int err, int fn, const char *why) +{ + if (err < 0) + post("ALSA %serror (%s): %s", + (fn == 1? "output " : (fn == 0 ? "input ": "")), + why, snd_strerror(err)); +} + +/* figure out, when opening ALSA device, whether we should use the code in +this file or defer to Winfried Ritch's code to do mmaped transfers (handled +in s_audio_alsamm.c). */ +static int alsaio_canmmap(t_alsa_dev *dev) +{ + snd_pcm_hw_params_t *hw_params; + int err1, err2; + + snd_pcm_hw_params_alloca(&hw_params); + + err1 = snd_pcm_hw_params_any(dev->a_handle, hw_params); + if (err1 < 0) { + check_error(err1, -1, "snd_pcm_hw_params_any"); + return (0); + } + err1 = snd_pcm_hw_params_set_access(dev->a_handle, + hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); + if (err1 < 0) + { + err2 = snd_pcm_hw_params_set_access(dev->a_handle, + hw_params, SND_PCM_ACCESS_MMAP_NONINTERLEAVED); + } + else err2 = -1; +#if 0 + post("err 1 %d (%s), err2 %d (%s)", err1, snd_strerror(err1), + err2, snd_strerror(err2)); +#endif + return ((err1 < 0) && (err2 >= 0)); +} + +/* set up an input or output device. Return 0 on success, -1 on failure. */ +static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate, + int nfrags, int frag_size) +{ + int bufsizeforthis, err; + snd_pcm_hw_params_t* hw_params; + snd_pcm_sw_params_t* sw_params; + unsigned int tmp_uint; + snd_pcm_uframes_t tmp_snd_pcm_uframes; + + snd_pcm_hw_params_alloca(&hw_params); + snd_pcm_sw_params_alloca(&sw_params); + + if (sys_verbose) + post((out ? "configuring sound output..." : + "configuring sound input...")); + + /* set hardware parameters... */ + + /* get the default params */ + err = snd_pcm_hw_params_any(dev->a_handle, hw_params); + check_error(err, out, "snd_pcm_hw_params_any"); + + /* try to set interleaved access */ + err = snd_pcm_hw_params_set_access(dev->a_handle, + hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); + if (err < 0) + return (-1); + check_error(err, out, "snd_pcm_hw_params_set_access"); +#if 0 /* enable this to print out which formats are available */ + { + int i; + for (i = 0; i <= SND_PCM_FORMAT_LAST; i++) + fprintf(stderr, "%d -> %d\n", + i, snd_pcm_hw_params_test_format(dev->a_handle, hw_params, i)); + } +#endif + /* Try to set 32 bit format first */ + err = snd_pcm_hw_params_set_format(dev->a_handle, + hw_params, SND_PCM_FORMAT_S32); + if (err < 0) + { + err = snd_pcm_hw_params_set_format(dev->a_handle, hw_params, + SND_PCM_FORMAT_S24_3LE); + if (err < 0) + { + err = snd_pcm_hw_params_set_format(dev->a_handle, hw_params, + SND_PCM_FORMAT_S16); + check_error(err, out, "_pcm_hw_params_set_format"); + dev->a_sampwidth = 2; + } + else dev->a_sampwidth = 3; + } + else dev->a_sampwidth = 4; + + if (sys_verbose) + post("Sample width set to %d bytes", dev->a_sampwidth); + + /* set the subformat */ + err = snd_pcm_hw_params_set_subformat(dev->a_handle, + hw_params, SND_PCM_SUBFORMAT_STD); + check_error(err, out, "snd_pcm_hw_params_set_subformat"); + + /* set the number of channels */ + tmp_uint = *channels; + err = snd_pcm_hw_params_set_channels_near(dev->a_handle, + hw_params, &tmp_uint); + check_error(err, out, "snd_pcm_hw_params_set_channels"); + if (tmp_uint != (unsigned)*channels) + post("ALSA: set %s channels to %d", (out?"output":"input"), tmp_uint); + *channels = tmp_uint; + dev->a_channels = *channels; + + /* set the sampling rate */ + err = snd_pcm_hw_params_set_rate_near(dev->a_handle, hw_params, + (unsigned int *)rate, 0); + check_error(err, out, "snd_pcm_hw_params_set_rate_min"); +#if 0 + err = snd_pcm_hw_params_get_rate(hw_params, &subunitdir); + post("input sample rate %d", err); +#endif + + /* post("frag size %d, nfrags %d", frag_size, nfrags); */ + /* set "period size" */ + tmp_snd_pcm_uframes = frag_size; + err = snd_pcm_hw_params_set_period_size_near(dev->a_handle, + hw_params, &tmp_snd_pcm_uframes, 0); + check_error(err, out, "snd_pcm_hw_params_set_period_size_near"); + + /* set the buffer size */ + tmp_snd_pcm_uframes = nfrags * frag_size; + err = snd_pcm_hw_params_set_buffer_size_near(dev->a_handle, + hw_params, &tmp_snd_pcm_uframes); + check_error(err, out, "snd_pcm_hw_params_set_buffer_size_near"); + + err = snd_pcm_hw_params(dev->a_handle, hw_params); + check_error(err, out, "snd_pcm_hw_params"); + + /* set up the buffer */ + bufsizeforthis = DEFDACBLKSIZE * dev->a_sampwidth * *channels; + if (alsa_snd_buf) + { + if (alsa_snd_bufsize < bufsizeforthis) + { + if (!(alsa_snd_buf = realloc(alsa_snd_buf, bufsizeforthis))) + { + post("out of memory"); + return (-1); + } + memset(alsa_snd_buf, 0, bufsizeforthis); + alsa_snd_bufsize = bufsizeforthis; + } + } + else + { + if (!(alsa_snd_buf = (void *)malloc(bufsizeforthis))) + { + post("out of memory"); + return (-1); + } + memset(alsa_snd_buf, 0, bufsizeforthis); + alsa_snd_bufsize = bufsizeforthis; + } + + err = snd_pcm_sw_params_current(dev->a_handle, sw_params); + if (err < 0) + { + post("Unable to determine current swparams for %s: %s\n", + (out ? "output" : "input"), snd_strerror(err)); + return (-1); + } + err = snd_pcm_sw_params_set_stop_threshold(dev->a_handle, sw_params, + 0x7fffffff); + if (err < 0) + { + post("Unable to set start threshold mode for %s: %s\n", + (out ? "output" : "input"), snd_strerror(err)); + return (-1); + } + + err = snd_pcm_sw_params_set_avail_min(dev->a_handle, sw_params, 4); + if (err < 0) + { + post("Unable to set avail min for %s: %s\n", + (out ? "output" : "input"), snd_strerror(err)); + return (-1); + } + err = snd_pcm_sw_params(dev->a_handle, sw_params); + if (err < 0) + { + post("Unable to set sw params for %s: %s\n", + (out ? "output" : "input"), snd_strerror(err)); + return (-1); + } + + return (0); +} + + + /* return 0 on success */ +int alsa_open_audio(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate, int blocksize) +{ + int err, inchans = 0, outchans = 0, subunitdir; + char devname[512]; + snd_output_t* out; + int frag_size = (blocksize ? blocksize : ALSA_DEFFRAGSIZE); + int nfrags, i, iodev, dev2; + int wantinchans, wantoutchans, device; + + nfrags = sys_schedadvance * (float)rate / (1e6 * frag_size); + /* save our belief as to ALSA's buffer size for later */ + alsa_buf_samps = nfrags * frag_size; + alsa_nindev = alsa_noutdev = 0; + alsa_jittermax = ALSA_DEFJITTERMAX; + + if (sys_verbose) + post("audio buffer set to %d", (int)(0.001 * sys_schedadvance)); + + for (iodev = 0; iodev < naudioindev; iodev++) + { + alsa_numbertoname(audioindev[iodev], devname, 512); + err = snd_pcm_open(&alsa_indev[alsa_nindev].a_handle, devname, + SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); + check_error(err, 0, "snd_pcm_open"); + if (err < 0) + continue; + alsa_indev[alsa_nindev].a_devno = audioindev[iodev]; + snd_pcm_nonblock(alsa_indev[alsa_nindev].a_handle, 1); + if (sys_verbose) + post("opened input device name %s", devname); + alsa_nindev++; + } + for (iodev = 0; iodev < naudiooutdev; iodev++) + { + alsa_numbertoname(audiooutdev[iodev], devname, 512); + err = snd_pcm_open(&alsa_outdev[alsa_noutdev].a_handle, devname, + SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); + check_error(err, 1, "snd_pcm_open"); + if (err < 0) + continue; + alsa_outdev[alsa_noutdev].a_devno = audiooutdev[iodev]; + snd_pcm_nonblock(alsa_outdev[alsa_noutdev].a_handle, 1); + alsa_noutdev++; + } + if (!alsa_nindev && !alsa_noutdev) + goto blewit; + + /* If all the open devices support mmap_noninterleaved, let's call + Wini's code in s_audio_alsamm.c */ + alsa_usemmap = 1; + for (iodev = 0; iodev < alsa_nindev; iodev++) + if (!alsaio_canmmap(&alsa_indev[iodev])) + alsa_usemmap = 0; + for (iodev = 0; iodev < alsa_noutdev; iodev++) + if (!alsaio_canmmap(&alsa_outdev[iodev])) + alsa_usemmap = 0; + if (alsa_usemmap) + { + post("using mmap audio interface"); + if (alsamm_open_audio(rate, blocksize)) + goto blewit; + else return (0); + } + for (iodev = 0; iodev < alsa_nindev; iodev++) + { + int channels = chindev[iodev]; + if (alsaio_setup(&alsa_indev[iodev], 0, &channels, &rate, + nfrags, frag_size) < 0) + goto blewit; + inchans += channels; + } + for (iodev = 0; iodev < alsa_noutdev; iodev++) + { + int channels = choutdev[iodev]; + if (alsaio_setup(&alsa_outdev[iodev], 1, &channels, &rate, + nfrags, frag_size) < 0) + goto blewit; + outchans += channels; + } + if (!inchans && !outchans) + goto blewit; + + for (iodev = 0; iodev < alsa_nindev; iodev++) + snd_pcm_prepare(alsa_indev[iodev].a_handle); + for (iodev = 0; iodev < alsa_noutdev; iodev++) + snd_pcm_prepare(alsa_outdev[iodev].a_handle); + + /* if duplex we can link the channels so they start together */ + for (iodev = 0; iodev < alsa_nindev; iodev++) + for (dev2 = 0; dev2 < alsa_noutdev; dev2++) + { + if (alsa_indev[iodev].a_devno == alsa_outdev[iodev].a_devno) + { + snd_pcm_link(alsa_indev[iodev].a_handle, + alsa_outdev[iodev].a_handle); + } + } + + /* allocate the status variables */ + if (!alsa_status) + { + err = snd_pcm_status_malloc(&alsa_status); + check_error(err, -1, "snd_pcm_status_malloc"); + } + + /* fill the buffer with silence and prime the output FIFOs. This + should automatically start the output devices. */ + memset(alsa_snd_buf, 0, alsa_snd_bufsize); + + if (outchans) + { + i = (frag_size * nfrags)/DEFDACBLKSIZE + 1; + while (i--) + { + for (iodev = 0; iodev < alsa_noutdev; iodev++) + snd_pcm_writei(alsa_outdev[iodev].a_handle, alsa_snd_buf, + DEFDACBLKSIZE); + } + } + if (inchans) + { + /* some of the ADC devices might already have been started by + starting the outputs above, but others might still need it. */ + for (iodev = 0; iodev < alsa_nindev; iodev++) + if (snd_pcm_state(alsa_indev[iodev].a_handle) + != SND_PCM_STATE_RUNNING) + if ((err = snd_pcm_start(alsa_indev[iodev].a_handle)) < 0) + check_error(err, -1, "input start failed"); + } + return (0); +blewit: + STUFF->st_inchannels = 0; + STUFF->st_outchannels = 0; + alsa_close_audio(); + return (1); +} + +void alsa_close_audio(void) +{ + int err, iodev; + if (alsa_usemmap) + { + alsamm_close_audio(); + return; + } + for (iodev = 0; iodev < alsa_nindev; iodev++) + { + err = snd_pcm_close(alsa_indev[iodev].a_handle); + check_error(err, 0, "snd_pcm_close"); + } + for (iodev = 0; iodev < alsa_noutdev; iodev++) + { + err = snd_pcm_close(alsa_outdev[iodev].a_handle); + check_error(err, 1, "snd_pcm_close"); + } + alsa_nindev = alsa_noutdev = 0; +} + +int alsa_send_dacs(void) +{ + static double timenow; + double timelast; + t_sample *fp, *fp1, *fp2; + int i, j, k, err, iodev, result, ch, resync = 0;; + int chansintogo, chansouttogo; + unsigned int transfersize; + + if (alsa_usemmap) + return (alsamm_send_dacs()); + + if (!alsa_nindev && !alsa_noutdev) + return (SENDDACS_NO); + + chansintogo = STUFF->st_inchannels; + chansouttogo = STUFF->st_outchannels; + transfersize = DEFDACBLKSIZE; + + timelast = timenow; + timenow = sys_getrealtime(); + +#ifdef DEBUG_ALSA_XFER + if (timenow - timelast > 0.050) + post("long wait between calls: %d", + (int)(1000 * (timenow - timelast))), fflush(stderr); + callno++; +#endif + + + for (iodev = 0; iodev < alsa_nindev; iodev++) + { + result = snd_pcm_state(alsa_indev[iodev].a_handle); + if (result == SND_PCM_STATE_XRUN) + { + int res2 = snd_pcm_start(alsa_indev[iodev].a_handle); + fprintf(stderr, "restart alsa input\n"); + if (res2 < 0) + fprintf(stderr, "alsa xrun recovery apparently failed\n"); + } + snd_pcm_status(alsa_indev[iodev].a_handle, alsa_status); + if (snd_pcm_status_get_avail(alsa_status) < transfersize) + return (SENDDACS_NO); + } + for (iodev = 0; iodev < alsa_noutdev; iodev++) + { + result = snd_pcm_state(alsa_outdev[iodev].a_handle); + if (result == SND_PCM_STATE_XRUN) + { + int res2 = snd_pcm_start(alsa_outdev[iodev].a_handle); + fprintf(stderr, "restart alsa output\n"); + if (res2 < 0) + fprintf(stderr, "alsa xrun recovery apparently failed\n"); + } + snd_pcm_status(alsa_outdev[iodev].a_handle, alsa_status); + if (snd_pcm_status_get_avail(alsa_status) < transfersize) + return (SENDDACS_NO); + } + +#ifdef DEBUG_ALSA_XFER + post("xfer %d", transfersize); +#endif + /* do output */ + for (iodev = 0, fp1 = STUFF->st_soundout, ch = 0; + iodev < alsa_noutdev; iodev++) + { + int thisdevchans = alsa_outdev[iodev].a_channels; + int chans = (chansouttogo < thisdevchans ? chansouttogo : thisdevchans); + chansouttogo -= chans; + + if (alsa_outdev[iodev].a_sampwidth == 4) + { + for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE) + for (j = i, k = DEFDACBLKSIZE, fp2 = fp1; k--; + j += thisdevchans, fp2++) + { + float s1 = *fp2 * INT32_MAX; + ((t_alsa_sample32 *)alsa_snd_buf)[j] = CLIP32(s1); + } + for (; i < thisdevchans; i++, ch++) + for (j = i, k = DEFDACBLKSIZE; k--; j += thisdevchans) + ((t_alsa_sample32 *)alsa_snd_buf)[j] = 0; + } + else if (alsa_outdev[iodev].a_sampwidth == 3) + { + for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE) + for (j = i, k = DEFDACBLKSIZE, fp2 = fp1; k--; + j += thisdevchans, fp2++) + { + int s = *fp2 * 8388352.; + if (s > 8388351) + s = 8388351; + else if (s < -8388351) + s = -8388351; +#if BYTE_ORDER == LITTLE_ENDIAN + ((char *)(alsa_snd_buf))[3*j] = (s & 255); + ((char *)(alsa_snd_buf))[3*j+1] = ((s>>8) & 255); + ((char *)(alsa_snd_buf))[3*j+2] = ((s>>16) & 255); +#else + fprintf(stderr, "big endian 24-bit not supported"); +#endif + } + for (; i < thisdevchans; i++, ch++) + for (j = i, k = DEFDACBLKSIZE; k--; j += thisdevchans) + ((char *)(alsa_snd_buf))[3*j] = + ((char *)(alsa_snd_buf))[3*j+1] = + ((char *)(alsa_snd_buf))[3*j+2] = 0; + } + else /* 16 bit samples */ + { + for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE) + for (j = ch, k = DEFDACBLKSIZE, fp2 = fp1; k--; + j += thisdevchans, fp2++) + { + int s = *fp2 * 32767.; + if (s > 32767) + s = 32767; + else if (s < -32767) + s = -32767; + ((t_alsa_sample16 *)alsa_snd_buf)[j] = s; + } + for (; i < thisdevchans; i++, ch++) + for (j = ch, k = DEFDACBLKSIZE; k--; j += thisdevchans) + ((t_alsa_sample16 *)alsa_snd_buf)[j] = 0; + } + result = snd_pcm_writei(alsa_outdev[iodev].a_handle, alsa_snd_buf, + transfersize); + + if (result != (int)transfersize) + { + #ifdef DEBUG_ALSA_XFER + if (result >= 0 || errno == EAGAIN) + post("ALSA: write returned %d of %d\n", + result, transfersize); + else post("ALSA: write: %s\n", + snd_strerror(errno)); + #endif + sys_log_error(ERR_DATALATE); + if (result == -EPIPE) + { + result = snd_pcm_prepare(alsa_indev[iodev].a_handle); + if (result < 0) + fprintf(stderr, "read reset error %d\n", result); + } + else fprintf(stderr, "read other error %d\n", result); + resync = 1; + } + + /* zero out the output buffer */ + memset(STUFF->st_soundout, 0, DEFDACBLKSIZE * sizeof(*STUFF->st_soundout) * + STUFF->st_outchannels); + if (sys_getrealtime() - timenow > 0.002) + { + #ifdef DEBUG_ALSA_XFER + post("output %d took %d msec\n", + callno, (int)(1000 * (timenow - timelast))), fflush(stderr); + #endif + timenow = sys_getrealtime(); + sys_log_error(ERR_DACSLEPT); + } + } + + /* do input */ + for (iodev = 0, fp1 = STUFF->st_soundin, ch = 0; iodev < alsa_nindev; iodev++) + { + int thisdevchans = alsa_indev[iodev].a_channels; + int chans = (chansintogo < thisdevchans ? chansintogo : thisdevchans); + chansouttogo -= chans; + result = snd_pcm_readi(alsa_indev[iodev].a_handle, alsa_snd_buf, + transfersize); + if (result < (int)transfersize) + { +#ifdef DEBUG_ALSA_XFER + if (result < 0) + post("snd_pcm_read %d %d: %s\n", + callno, xferno, snd_strerror(errno)); + else post("snd_pcm_read %d %d returned only %d\n", + callno, xferno, result); +#endif + sys_log_error(ERR_DATALATE); + if (result == -EPIPE) + { + result = snd_pcm_prepare(alsa_indev[iodev].a_handle); + if (result < 0) + fprintf(stderr, "read reset error %d\n", result); + } + else fprintf(stderr, "read other error %d\n", result); + resync = 1; + } + if (alsa_indev[iodev].a_sampwidth == 4) + { + for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE) + { + for (j = ch, k = DEFDACBLKSIZE, fp2 = fp1; k--; + j += thisdevchans, fp2++) + *fp2 = (float) ((t_alsa_sample32 *)alsa_snd_buf)[j] + * (1./ INT32_MAX); + } + } + else if (alsa_indev[iodev].a_sampwidth == 3) + { +#if BYTE_ORDER == LITTLE_ENDIAN + for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE) + { + for (j = ch, k = DEFDACBLKSIZE, fp2 = fp1; k--; + j += thisdevchans, fp2++) + *fp2 = ((float) ( + (((unsigned char *)alsa_snd_buf)[3*j] << 8) + | (((unsigned char *)alsa_snd_buf)[3*j+1] << 16) + | (((unsigned char *)alsa_snd_buf)[3*j+2] << 24))) + * (1./ INT32_MAX); + } +#else + fprintf(stderr, "big endian 24-bit not supported"); +#endif + } + else + { + for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE) + { + for (j = ch, k = DEFDACBLKSIZE, fp2 = fp1; k--; + j += thisdevchans, fp2++) + *fp2 = (float) ((t_alsa_sample16 *)alsa_snd_buf)[j] + * 3.051850e-05; + } + } + } +#ifdef DEBUG_ALSA_XFER + xferno++; +#endif + if (sys_getrealtime() - timenow > 0.002) + { +#ifdef DEBUG_ALSA_XFER + post("alsa_send_dacs took %d msec\n", + (int)(1000 * (sys_getrealtime() - timenow))); +#endif + sys_log_error(ERR_ADCSLEPT); + } + { + static int checkcountdown = 0; + if (!checkcountdown--) + { + checkcountdown = 10; + if (alsa_nindev + alsa_noutdev > 1) + alsa_checkiosync(); /* check I/O are in sync */ + } + } + return SENDDACS_YES; +} + +void alsa_printstate( void) +{ + int i, result, iodev = 0; + snd_pcm_sframes_t indelay = 0, outdelay = 0; + if (sys_audioapi != API_ALSA) + { + error("restart-audio: implemented for ALSA only."); + return; + } + if (STUFF->st_inchannels) + { + result = snd_pcm_delay(alsa_indev[iodev].a_handle, &indelay); + if (result < 0) + post("snd_pcm_delay 1 failed"); + else post("in delay %d", indelay); + } + if (STUFF->st_outchannels) + { + result = snd_pcm_delay(alsa_outdev[iodev].a_handle, &outdelay); + if (result < 0) + post("snd_pcm_delay 2 failed"); + else post("out delay %d", outdelay); + } + post("sum %d (%d mod 64)\n", indelay + outdelay, (indelay+outdelay)%64); + + post("buf samples %d", alsa_buf_samps); +} + +void alsa_putzeros(int iodev, int n) +{ + int i, result; + memset(alsa_snd_buf, 0, + alsa_outdev[iodev].a_sampwidth * DEFDACBLKSIZE * + alsa_outdev[iodev].a_channels); + for (i = 0; i < n; i++) + { + result = snd_pcm_writei(alsa_outdev[iodev].a_handle, alsa_snd_buf, + DEFDACBLKSIZE); +#if 0 + if (result != DEFDACBLKSIZE) + post("result %d", result); +#endif + } + /* post ("putzeros %d", n); */ +} + +void alsa_getzeros(int iodev, int n) +{ + int i, result; + for (i = 0; i < n; i++) + { + result = snd_pcm_readi(alsa_indev[iodev].a_handle, alsa_snd_buf, + DEFDACBLKSIZE); +#if 0 + if (result != DEFDACBLKSIZE) + post("result %d", result); +#endif + } + /* post ("getzeros %d", n); */ +} + + /* call this only if both input and output are open */ +static void alsa_checkiosync( void) +{ + int i, result, giveup = 50, alreadylogged = 0, iodev = 0, err; + snd_pcm_sframes_t minphase, maxphase, thisphase, outdelay; + + while (1) + { + if (giveup-- <= 0) + { + post("tried but couldn't sync A/D/A"); + alsa_jittermax += 1; + return; + } + minphase = 0x7fffffff; + maxphase = -0x7fffffff; + for (iodev = 0; iodev < alsa_noutdev; iodev++) + { + if ((result = snd_pcm_state(alsa_outdev[iodev].a_handle)) + != SND_PCM_STATE_RUNNING && result != SND_PCM_STATE_XRUN) + { + if (sys_verbose) + post("restarting output device from state %d", + snd_pcm_state(alsa_outdev[iodev].a_handle)); + if ((err = snd_pcm_start(alsa_outdev[iodev].a_handle)) < 0) + check_error(err, 0, "restart failed"); + } + result = snd_pcm_delay(alsa_outdev[iodev].a_handle, &outdelay); + if (result < 0) + { + snd_pcm_prepare(alsa_outdev[iodev].a_handle); + result = snd_pcm_delay(alsa_outdev[iodev].a_handle, &outdelay); + } +#ifdef DEBUG_ALSA_XFER + post("outfifo %d %d %d", + callno, xferno, outdelay); +#endif + if (result < 0) + { + post("output snd_pcm_delay failed: %s", snd_strerror(result)); + if (snd_pcm_status(alsa_outdev[iodev].a_handle, + alsa_status) < 0) + post("output snd_pcm_status failed"); + else post("astate %d", + snd_pcm_status_get_state(alsa_status)); + return; + } + thisphase = alsa_buf_samps - outdelay; + if (thisphase < minphase) + minphase = thisphase; + if (thisphase > maxphase) + maxphase = thisphase; + if (outdelay < 0) + sys_log_error(ERR_DATALATE), alreadylogged = 1; + } + for (iodev = 0; iodev < alsa_nindev; iodev++) + { + if ((result = snd_pcm_state(alsa_indev[iodev].a_handle)) + != SND_PCM_STATE_RUNNING && result != SND_PCM_STATE_XRUN) + { + if (sys_verbose) + post("restarting input device from state %d", + snd_pcm_state(alsa_indev[iodev].a_handle)); + if ((err = snd_pcm_start(alsa_indev[iodev].a_handle)) < 0) + check_error(err, 1, "restart failed"); + } + result = snd_pcm_delay(alsa_indev[iodev].a_handle, &thisphase); + if (result < 0) + { + snd_pcm_prepare(alsa_indev[iodev].a_handle); + result = snd_pcm_delay(alsa_indev[iodev].a_handle, &thisphase); + } +#ifdef DEBUG_ALSA_XFER + post("infifo %d %d %d", + callno, xferno, thisphase); +#endif + if (result < 0) + { + post("output snd_pcm_delay failed: %s", snd_strerror(result)); + if (snd_pcm_status(alsa_outdev[iodev].a_handle, + alsa_status) < 0) + post("output snd_pcm_status failed"); + else post("astate %d", + snd_pcm_status_get_state(alsa_status)); + return; + } + if (thisphase < minphase) + minphase = thisphase; + if (thisphase > maxphase) + maxphase = thisphase; + } + /* the "correct" position is for all the phases to be exactly + equal; but since we only make corrections DEFDACBLKSIZE samples + at a time, we just ask that the spread be not more than 3/4 + of a block. */ + if (maxphase <= minphase + (alsa_jittermax * (DEFDACBLKSIZE / 4))) + break; + +#ifdef DEBUG_ALSA_XFER + post("resync audio %d %d %d", xferno, minphase, maxphase); +#endif + + for (iodev = 0; iodev < alsa_noutdev; iodev++) + { + result = snd_pcm_delay(alsa_outdev[iodev].a_handle, &outdelay); + if (result < 0) + break; + thisphase = alsa_buf_samps - outdelay; + if (thisphase > minphase + DEFDACBLKSIZE) + { + alsa_putzeros(iodev, 1); + if (!alreadylogged) + sys_log_error(ERR_RESYNC), alreadylogged = 1; +#ifdef DEBUG_ALSA_XFER + post("putz %d %d %d %d", + callno, xferno, (int)thisphase, (int)minphase); +#endif + } + } + for (iodev = 0; iodev < alsa_nindev; iodev++) + { + result = snd_pcm_delay(alsa_indev[iodev].a_handle, &thisphase); + if (result < 0) + break; + if (thisphase > minphase + DEFDACBLKSIZE) + { + alsa_getzeros(iodev, 1); + if (!alreadylogged) + sys_log_error(ERR_RESYNC), alreadylogged = 1; +#ifdef DEBUG_ALSA_XFER + post("getz %d %d %d %d", + callno, xferno, (int)thisphase, (int)minphase); +#endif + } + } + /* it's possible we didn't do anything; if so don't repeat */ + if (!alreadylogged) + break; + } +#ifdef DEBUG_ALSA_XFER + if (alreadylogged) + post("done resync"); +#endif +} + +static int alsa_nnames = 0; +static char **alsa_names = 0; + +void alsa_adddev(char *name) +{ + if (alsa_nnames) + alsa_names = (char **)t_resizebytes(alsa_names, + alsa_nnames * sizeof(char *), + (alsa_nnames+1) * sizeof(char *)); + else alsa_names = (char **)t_getbytes(sizeof(char *)); + alsa_names[alsa_nnames] = gensym(name)->s_name; + alsa_nnames++; +} + +static void alsa_numbertoname(int devno, char *devname, int nchar) +{ + int ndev = 0, cardno = -1; + while (!snd_card_next(&cardno) && cardno >= 0) + ndev++; + if (devno < 2*ndev) + { + if (devno & 1) + snprintf(devname, nchar, "plughw:%d", devno/2); + else snprintf(devname, nchar, "hw:%d", devno/2); + } + else if (devno <2*ndev + alsa_nnames) + snprintf(devname, nchar, "%s", alsa_names[devno - 2*ndev]); + else snprintf(devname, nchar, "???"); +} + + /* For each hardware card found, we list two devices, the "hard" and + "plug" one. The card scan is derived from portaudio code. */ +void alsa_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize) +{ + int ndev = 0, cardno = -1, i, j; + *canmulti = 2; /* supports multiple devices */ + while (!snd_card_next(&cardno) && cardno >= 0) + { + snd_ctl_t *ctl; + snd_ctl_card_info_t *info; + char devname[80]; + const char *desc; + if (2 * ndev + 2 > maxndev) + break; + sprintf(devname, "hw:%d", cardno ); + /* fprintf(stderr, "\ntry %s...\n", devname); */ + if (snd_ctl_open(&ctl, devname, 0) >= 0) + { + snd_ctl_card_info_malloc(&info); + snd_ctl_card_info(ctl, info); + desc = snd_ctl_card_info_get_name(info); + snprintf(indevlist + 2*ndev * devdescsize, devdescsize, + "%s (hardware)", desc); + snprintf(indevlist + (2*ndev + 1) * devdescsize, devdescsize, + "%s (plug-in)", desc); + snprintf(outdevlist + 2*ndev * devdescsize, devdescsize, + "%s (hardware)", desc); + snprintf(outdevlist + (2*ndev + 1) * devdescsize, devdescsize, + "%s (plug-in)", desc); + indevlist[(2*ndev+1) * devdescsize - 1] = + indevlist[(2*ndev+2) * devdescsize - 1] = + outdevlist[(2*ndev+1) * devdescsize - 1] = + outdevlist[(2*ndev+2) * devdescsize - 1] = 0; + snd_ctl_card_info_free(info); + } + else + { + fprintf(stderr, "ALSA card scan error\n"); + sprintf(indevlist + 2*ndev * devdescsize, "???"); + sprintf(indevlist + (2*ndev + 1) * devdescsize, "???"); + sprintf(outdevlist + 2*ndev * devdescsize, "???"); + sprintf(outdevlist + (2*ndev + 1) * devdescsize, "???"); + } + /* fprintf(stderr, "name: %s\n", snd_ctl_card_info_get_name(info)); */ + ndev++; + } + for (i = 0, j = 2*ndev; i < alsa_nnames; i++, j++) + { + if (j >= maxndev) + break; + snprintf(indevlist + j * devdescsize, devdescsize, "%s", + alsa_names[i]); + snprintf(outdevlist + j * devdescsize, devdescsize, "%s", + alsa_names[i]); + indevlist[(i+1) * devdescsize - 1] = + outdevlist[(i+1) * devdescsize - 1] = 0; + } + *nindevs = *noutdevs = j; +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_audio_alsa.h b/ports/camomile/source/LibPd/pure-data/src/s_audio_alsa.h new file mode 100644 index 00000000..99367637 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_audio_alsa.h @@ -0,0 +1,40 @@ +/* Copyright (c) 1997- Guenter Geiger, Miller Puckette, Larry Troxler, +* Winfried Ritsch, Karl MacMillan, and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + + +typedef int16_t t_alsa_sample16; +typedef int32_t t_alsa_sample32; +#define ALSA_SAMPLEWIDTH_16 sizeof(t_alsa_sample16) +#define ALSA_SAMPLEWIDTH_32 sizeof(t_alsa_sample32) +#define ALSA_XFERSIZE16 (signed int)(sizeof(t_alsa_sample16) * DEFDACBLKSIZE) +#define ALSA_XFERSIZE32 (signed int)(sizeof(t_alsa_sample32) * DEFDACBLKSIZE) +#define ALSA_MAXDEV 4 +#define ALSA_JITTER 1024 +#define ALSA_EXTRABUFFER 2048 +#define ALSA_DEFFRAGSIZE 64 +#define ALSA_DEFNFRAG 12 + +#ifndef INT32_MAX +#define INT32_MAX 0x7fffffff +#endif + +typedef struct _alsa_dev +{ + snd_pcm_t *a_handle; + int a_devno; + int a_sampwidth; + int a_channels; + char **a_addr; + int a_synced; +} t_alsa_dev; + +extern t_alsa_dev alsa_indev[ALSA_MAXDEV]; +extern t_alsa_dev alsa_outdev[ALSA_MAXDEV]; +extern int alsa_nindev; +extern int alsa_noutdev; + +int alsamm_open_audio(int rate, int blocksize); +void alsamm_close_audio(void); +int alsamm_send_dacs(void); diff --git a/ports/camomile/source/LibPd/pure-data/src/s_audio_alsamm.c b/ports/camomile/source/LibPd/pure-data/src/s_audio_alsamm.c new file mode 100644 index 00000000..df6c603e --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_audio_alsamm.c @@ -0,0 +1,1365 @@ +/* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler, +* Winfried Ritsch, Karl MacMillan, and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* + this audiodriverinterface inputs and outputs audio data using + the ALSA MMAP API available on linux. + this is optimized for hammerfall cards and does not make an attempt to be general + now, please adapt to your needs or let me know ... + constrains now: + - audio Card with ALSA-Driver > 1.0.3, + - alsa-device (preferable hw) with MMAP NONINTERLEAVED SIGNED-32Bit features + - up to 4 cards with has to be hardwaresynced + (winfried) +*/ +#include + +#include "m_pd.h" +#include "s_stuff.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "s_audio_alsa.h" + +/* needed for alsa 0.9 compatibility: */ +#if (SND_LIB_MAJOR < 1) +#define ALSAAPI9 +#endif +/* sample type magic ... + Hammerfall/HDSP/DSPMADI cards always 32Bit where lower 8Bit not used (played) in AD/DA, + but can have some bits set (subchannel coding) +*/ +/* sample type magic ... + Hammerfall/HDSP/DSPMADI cards always 32Bit where lower 8Bit not used (played) in AD/DA, + but can have some bits set (subchannel coding) +*/ + +#define ALSAMM_SAMPLEWIDTH_32 sizeof(t_alsa_sample32) + +#ifndef INT32_MAX +#define INT32_MAX 0x7fffffff +#endif + +/* maybe: + don't assume we can turn all 31 bits when doing float-to-fix; + otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. + + but not now on hammerfall (w) +*/ + +/* 24 Bit are used so MAX Samplevalue not INT32_MAX ??? */ +#define F32MAX 0x7fffff00 +#define CLIP32(x) (((x)>F32MAX)?F32MAX:((x) < -F32MAX)?-F32MAX:(x)) + +#define ALSAMM_FORMAT SND_PCM_FORMAT_S32 +/* + maximum of 4 devices + you can mix rme9632,hdsp9632 (18 chans) rme9652,hdsp9652 (26 chans), dsp-madi (64 chans) + if synced +*/ + +/* the concept is holding data for each device + where a device is in and output and has one name. + + but since we can use only ins or only outs or both + on each hardware we list them in used_???device + for alsa separated for inputs and outputs + + due the need to link in and out-device on one card + and do only one mmap prepare and start for in and out + the concept turns out to be not very efficient, + so i will change it maybe in future... +*/ + +static int alsamm_incards = 0; +static t_alsa_dev *alsamm_indevice[ALSA_MAXDEV]; +static int alsamm_outcards = 0; +static t_alsa_dev *alsamm_outdevice[ALSA_MAXDEV]; + +/* + we need same samplerate, buffertime and so on for + each card soo we use global vars... + time is in us, size in frames (i hope so ;-) +*/ +static unsigned int alsamm_sr = 0; +static unsigned int alsamm_buffertime = 0; +static unsigned int alsamm_buffersize = 0; +static int alsamm_transfersize = DEFDACBLKSIZE; + +/* bad style: we asume all cards give the same answer at init so we make this vars global + to have a faster access in writing reading during send_dacs */ +static snd_pcm_sframes_t alsamm_period_size; +static unsigned int alsamm_periods; +static snd_pcm_sframes_t alsamm_buffer_size; + +/* if more than this sleep detected, should be more than periodsize/samplerate ??? */ +static double sleep_time; + +/* now we just sum all inputs/outputs of used cards to a global count + and use them all + ... later we should just use some channels of each card for pd + so we reduce the overhead of using alsways all channels, + and zero the rest once at start, + because rme9652 and hdsp forces us to use all channels + in mmap mode... + +Note on why: + normally hdsp and dspmadi can handle channel + count from one to all since they can switch on/off + the dma for them to reduce pci load, but this is only + implemented in alsa low level drivers for dspmadi now and maybe fixed for hdsp in future +*/ + +static int alsamm_inchannels = 0; +static int alsamm_outchannels = 0; + +/* Defines */ +/*#define ALSAMM_DEBUG */ +#ifdef ALSAMM_DEBUG + + #define DEBUG(x) x + #define DEBUG2(x) {x;} + + #define WATCH_PERIODS 90 + + static int in_avail[WATCH_PERIODS]; + static int out_avail[WATCH_PERIODS]; + static int in_offset[WATCH_PERIODS]; + static int out_offset[WATCH_PERIODS]; + static int out_cm[WATCH_PERIODS]; + static char *outaddr[WATCH_PERIODS]; + static char *inaddr[WATCH_PERIODS]; + static char *outaddr2[WATCH_PERIODS]; + static char *inaddr2[WATCH_PERIODS]; + static int xruns_watch[WATCH_PERIODS]; + static int broken_opipe; + + static int dac_send = 0; + static int alsamm_xruns = 0; + +static void show_availist(void) +{ + int i; + for(i=1;i= 0) { +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("Access type %s available","SND_PCM_ACCESS_MMAP_NONINTERLEAVED"); +#endif + } + else{ + check_error(err,"No Accesstype SND_PCM_ACCESS_MMAP_NONINTERLEAVED"); + return err; + } + + /* set the sample format */ + err = snd_pcm_hw_params_set_format(handle, params, ALSAMM_FORMAT); + if (err < 0) { + check_error(err,"Sample format not available for playback"); + return err; + } + +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("Setting format to %s",snd_pcm_format_name(ALSAMM_FORMAT)); +#endif + + /* first check samplerate since channels numbers + are samplerate dependent (double speed) */ + /* set the stream rate */ + + rrate = alsamm_sr; + +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("Samplerate request: %i Hz",rrate); +#endif + + dir=-1; + err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, &dir); + if (err < 0) { + check_error(err,"Rate not available"); + return err; + } + + if (rrate != alsamm_sr) { + post("Warning: rate %iHz doesn't match requested %iHz", rrate,alsamm_sr); + alsamm_sr = rrate; + } + else + if(sys_verbose) + post("Samplerate is set to %iHz",alsamm_sr); + + /* Info on channels */ + { + int maxchs,minchs,channels = *chs; + + if((err = snd_pcm_hw_params_get_channels_max(params, + (unsigned int *)&maxchs)) < 0){ + check_error(err,"Getting channels_max not available"); + return err; + } + if((err = snd_pcm_hw_params_get_channels_min(params, + (unsigned int *)&minchs)) < 0){ + check_error(err,"Getting channels_min not available"); + return err; + } + +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("Getting channels:min=%d, max= %d for request=%d",minchs,maxchs,channels); +#endif + if(channels < 0)channels=maxchs; + if(channels > maxchs)channels = maxchs; + if(channels < minchs)channels = minchs; + + if(channels != *chs) + post("requested channels=%d but used=%d",*chs,channels); + + *chs = channels; +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("trying to use channels: %d",channels); +#endif + } + + /* set the count of channels */ + err = snd_pcm_hw_params_set_channels(handle, params, *chs); + if (err < 0) { + check_error(err,"Channels count not available"); + return err; + } + + /* testing for channels */ + if((err = snd_pcm_hw_params_get_channels(params,(unsigned int *)chs)) < 0) + check_error(err,"Get channels not available"); +#ifdef ALSAMM_DEBUG + else + if(sys_verbose) + post("When setting channels count and got %d",*chs); +#endif + + /* if buffersize is set use this instead buffertime */ + if(alsamm_buffersize > 0){ + +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("hw_params: ask for max buffersize of %d samples", + (unsigned int) alsamm_buffersize ); +#endif + + alsamm_buffer_size = alsamm_buffersize; + + err = snd_pcm_hw_params_set_buffer_size_near(handle, params, + (unsigned long *)&alsamm_buffer_size); + if (err < 0) { + check_error(err,"Unable to set max buffer size"); + return err; + } + + } + else{ + if(alsamm_buffertime <= 0) /* should never happen, but use 20ms */ + alsamm_buffertime = 20000; + +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("hw_params: ask for max buffertime of %d ms", + (unsigned int) (alsamm_buffertime*0.001) ); +#endif + + err = snd_pcm_hw_params_set_buffer_time_near(handle, params, + &alsamm_buffertime, &dir); + if (err < 0) { + check_error(err,"Unable to set max buffer time"); + return err; + } + } + + err = snd_pcm_hw_params_get_buffer_time(params, + (unsigned int *)&alsamm_buffertime, &dir); + if (err < 0) { + check_error(err,"Unable to get buffer time"); + return err; + } + +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("hw_params: got buffertime to %f ms", + (float) (alsamm_buffertime*0.001)); +#endif + + err = snd_pcm_hw_params_get_buffer_size(params, + (unsigned long *)&alsamm_buffer_size); + if (err < 0) { + check_error(err,"Unable to get buffer size"); + return err; + } + +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("hw_params: got buffersize to %d samples",(int) alsamm_buffer_size); +#endif + + err = snd_pcm_hw_params_get_period_size(params, + (unsigned long *)&alsamm_period_size, &dir); + if (err > 0) { + check_error(err,"Unable to get period size"); + return err; + } + +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("Got period size of %d", (int) alsamm_period_size); +#endif + { + unsigned int pmin,pmax; + + err = snd_pcm_hw_params_get_periods_min(params, &pmin, &dir); + if (err > 0) { + check_error(err,"Unable to get period size"); + return err; + } + err = snd_pcm_hw_params_get_periods_min(params, &pmax, &dir); + if (err > 0) { + check_error(err,"Unable to get period size"); + return err; + } + + /* use maximum of periods */ + if( alsamm_periods <= 0) + alsamm_periods = pmax; + alsamm_periods = (alsamm_periods > pmax)?pmax:alsamm_periods; + alsamm_periods = (alsamm_periods < pmin)?pmin:alsamm_periods; + + err = snd_pcm_hw_params_set_periods(handle, params, alsamm_periods, dir); + if (err > 0) { + check_error(err,"Unable to set periods"); + return err; + } + + + err = snd_pcm_hw_params_get_periods(params, &pmin, &dir); + if (err > 0) { + check_error(err,"Unable to get periods"); + return err; + } +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("Got periods of %d, where periodsmin=%d, periodsmax=%d", + alsamm_periods,pmin,pmax); +#endif + } + + /* write the parameters to device */ + err = snd_pcm_hw_params(handle, params); + if (err < 0) { + check_error(err,"Unable to set hw params"); + return err; + } +#endif /* ALSAAPI9 */ + return 0; +} + +static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams, int playback) +{ +#ifndef ALSAAPI9 + int err; + snd_pcm_uframes_t ps,ops; + snd_pcm_uframes_t bs,obs; + + /* get the current swparams */ + err = snd_pcm_sw_params_current(handle, swparams); + if (err < 0) { + check_error(err,"Unable to determine current swparams for playback"); + return err; + } + + /* AUTOSTART: start the transfer on each write/commit ??? */ + snd_pcm_sw_params_get_start_threshold(swparams, &obs); + + err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0U); + if (err < 0) { + check_error(err,"Unable to set start threshold mode"); + return err; + } + + snd_pcm_sw_params_get_start_threshold(swparams, &bs); + +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("sw_params: got start_thresh_hold= %d (was %d)",(int) bs,(int)obs); +#endif + + /* AUTOSTOP: never stop the machine */ + + snd_pcm_sw_params_get_stop_threshold(swparams, &obs); + + err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, (snd_pcm_uframes_t)-1); + if (err < 0) { + check_error(err,"Unable to set stop threshold mode"); + return err; + } + + snd_pcm_sw_params_get_stop_threshold(swparams, &bs); +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("sw_params: set stop_thresh_hold= %d (was %d)", (int) bs,(int)obs); +#endif + + + /* AUTOSILENCE: silence if overrun.... */ + + snd_pcm_sw_params_get_silence_threshold (swparams, &ops); + if ((err = snd_pcm_sw_params_set_silence_threshold (handle, swparams, alsamm_period_size)) < 0) { + check_error (err,"cannot set silence threshold for"); + return -1; + } + snd_pcm_sw_params_get_silence_threshold (swparams, &ps); +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("sw_params: set silence_threshold = %d (was %d)", (int) ps,(int)ops); +#endif + + snd_pcm_sw_params_get_silence_size (swparams, &ops); + if ((err = snd_pcm_sw_params_set_silence_size(handle, swparams, alsamm_period_size)) < 0) { + check_error (err,"cannot set silence size for"); + return -1; + } + snd_pcm_sw_params_get_silence_size (swparams, &ps); +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("sw_params: set silence_size = %d (was %d)", (int) ps,(int)ops); +#endif + + /* AVAIL: allow the transfer when at least period_size samples can be processed */ + + snd_pcm_sw_params_get_avail_min(swparams, &ops); + + err = snd_pcm_sw_params_set_avail_min(handle, swparams, alsamm_transfersize/2); + if (err < 0) { + check_error(err,"Unable to set avail min for"); + return err; + } + + snd_pcm_sw_params_get_avail_min(swparams, &ps); +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("sw_params: set avail_min= %d (was %d)", (int) ps, (int) ops); +#endif + + /* write the parameters to the playback device */ + + err = snd_pcm_sw_params(handle, swparams); + if (err < 0) { + check_error(err,"Unable to set sw params"); + return err; + } + +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("set sw finished"); +#endif +#else + post("alsa: need version 1.0 or above for mmap operation"); +#endif /* ALSAAPI9 */ + return 0; +} + +/* ALSA Transfer helps */ + +/* xrun_recovery is called if time to late or error + + Note: use outhandle if synced i/o + the devices are linked so prepare + has only be called on out, + hopefully resume too... +*/ + +static int xrun_recovery(snd_pcm_t *handle, int err) +{ +#ifdef ALSAMM_DEBUG + alsamm_xruns++; /* count xruns */ +#endif + + if (err == -EPIPE) { /* under-run */ + err = snd_pcm_prepare(handle); + if (err < 0) + check_error(err,"Can't recovery from underrun, prepare failed."); + + err = snd_pcm_start(handle); + if (err < 0) + check_error(err,"Can't start when recover from underrun."); + + return 0; + } else if (err == -ESTRPIPE) { + while ((err = snd_pcm_resume(handle)) == -EAGAIN) + sleep(1); /* wait until the suspend flag is released */ + if (err < 0) { + err = snd_pcm_prepare(handle); + if (err < 0) + check_error(err,"Can't recovery from suspend, prepare failed."); + + err = snd_pcm_start(handle); + if (err < 0) + check_error(err,"Can't start when recover from underrun."); + } + return 0; + } + + return err; +} + +/* note that snd_pcm_avail has to be called before using this function */ + +static int alsamm_get_channels(snd_pcm_t *dev, + snd_pcm_uframes_t *avail, + snd_pcm_uframes_t *offset, + int nchns, char **addr) +{ + int err = 0; + int chn; + const snd_pcm_channel_area_t *mm_areas; + + + if (nchns > 0 && avail != NULL && offset != NULL) { + + if ((err = snd_pcm_mmap_begin(dev, &mm_areas, offset, avail)) < 0){ + check_error(err,"setmems: begin_mmap failure ???"); + return err; + } + + for (chn = 0; chn < nchns; chn++) { + const snd_pcm_channel_area_t *a = &mm_areas[chn]; + addr[chn] = (char *) a->addr + ((a->first + a->step * *offset) / 8); + } + + return err; + } + + return -1; +} + + +static int alsamm_start() +{ + int err = 0; + int devno; + int chn,nchns; + + const snd_pcm_channel_area_t *mm_areas; + +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("start audio with %d out cards and %d incards",alsamm_outcards,alsamm_incards); +#endif + + /* first prepare for in/out */ + for(devno = 0;devno < alsa_noutdev;devno++){ + + snd_pcm_uframes_t offset, avail; + t_alsa_dev *dev = &alsa_outdev[devno]; + + /* snd_pcm_prepare also in xrun, but cannot harm here */ + if ((err = snd_pcm_prepare (dev->a_handle)) < 0) { + check_error (err,"outcard prepare error for playback"); + return err; + } + + offset = 0; + avail = snd_pcm_avail_update(dev->a_handle); + + if (avail != (snd_pcm_uframes_t) alsamm_buffer_size) { + check_error (avail,"full buffer not available at start"); + } + + /* cleaning out mmap buffer before start */ + +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("start: set mems for avail=%d,offset=%d at buffersize=%d", + avail,offset,alsamm_buffer_size); +#endif + + if(avail > 0){ + + int comitted = 0; + + if ((err = alsamm_get_channels(dev->a_handle, &avail, &offset, + dev->a_channels,dev->a_addr)) < 0) { + check_error(err,"setting initial out channelspointer failure ?"); + continue; + } + + for (chn = 0; chn < dev->a_channels; chn++) + memset(dev->a_addr[chn],0,avail*ALSAMM_SAMPLEWIDTH_32); + + comitted = snd_pcm_mmap_commit (dev->a_handle, offset, avail); + + avail = snd_pcm_avail_update(dev->a_handle); + +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("start: now channels cleared, out with avail=%d, offset=%d,comitted=%d", + avail,offset,comitted); +#endif + } + /* now start, should be autostarted */ + avail = snd_pcm_avail_update(dev->a_handle); + +#ifdef ALSAMM_DEBUG + if(sys_verbose) + post("start: finish start, out with avail=%d, offset=%d",avail,offset); +#endif + + /* we have no autostart so anyway start*/ + if ((err = snd_pcm_start (dev->a_handle)) < 0) { + check_error (err,"could not start playback"); + } + } + + for(devno = 0;devno < alsa_nindev;devno++){ + + snd_pcm_uframes_t ioffset, iavail; + t_alsa_dev *dev = &alsa_indev[devno]; + + /* if devices are synced then don't need to prepare + hopefully dma in areas already filled correct by the card */ + + if(dev->a_synced == 0){ + if ((err = snd_pcm_prepare (dev->a_handle)) < 0) { + check_error (err,"incard prepare error for capture"); + /* return err;*/ + } + } + + ioffset = 0; + iavail = snd_pcm_avail_update (dev->a_handle); + + /* cleaning out mmap buffer before start */ +#ifdef ALSAMM_DEBUG + post("start in: set in mems for avail=%d,offset=%d at buffersize=%d", + iavail,ioffset,alsamm_buffer_size); +#endif + + if (iavail > (snd_pcm_uframes_t) 0) { + +#ifdef ALSAMM_DEBUG + post("empty buffer not available at start, since avail %d != %d buffersize", + iavail, alsamm_buffer_size); +#endif + + if ((err = alsamm_get_channels(dev->a_handle, &iavail, &ioffset, + dev->a_channels,dev->a_addr)) < 0) { + check_error(err,"getting in channelspointer failure ????"); + continue; + } + + snd_pcm_mmap_commit (dev->a_handle, ioffset, iavail); + + iavail = snd_pcm_avail_update (dev->a_handle); +#ifdef ALSAMM_DEBUG + post("start in now avail=%d",iavail); +#endif + } + +#ifdef ALSAMM_DEBUG + post("start: init inchannels with avail=%d, offset=%d",iavail,ioffset); +#endif + + /* if devices are synced then don't need to start */ + /* start with autostart , but anyway start */ + if(dev->a_synced == 0){ + if ((err = snd_pcm_start (dev->a_handle)) < 0) { + check_error (err,"could not start capture"); + continue; + } + } + + } + + return err; +} + +static int alsamm_stop() +{ + int err = 0; + int devno; + + /* first stop in... */ + for(devno = 0;devno < alsa_nindev;devno++){ + + t_alsa_dev *dev = &alsa_indev[devno]; + + if(sys_verbose) + post("stop in device %d",devno); + + if ((err = snd_pcm_drop(dev->a_handle)) < 0) { + check_error (err,"channel flush for capture failed"); + } + + } + + /* then outs */ + for(devno = 0;devno < alsa_noutdev;devno++){ + + + t_alsa_dev *dev = &alsa_outdev[devno]; + if(sys_verbose) + post("stop out device %d",devno); + + if ((err = snd_pcm_drop(dev->a_handle)) < 0) { + check_error (err,"channel flush for playback failed"); + } + + } + +#ifdef ALSAMM_DEBUG + show_availist(); +#endif + + return err; +} + + + +/* ---------- ADC/DAC transfer in the main loop ------- */ + +/* I see: (a guess as a documentation) + + all DAC data is in sys_soundout array with + DEFDACBLKSIZE (mostly 64) for each channels which + if we have more channels opened then dac-channels = sys_outchannels + we have to zero (silence them), which should be done once. + +Problems to solve: + + a) Since in ALSA MMAP, the MMAP reagion can change (don't ask me why) + we have to do it each cycle or we say on RME HAMMERFALL/HDSP/DSPMADI + it never changes to it once. so maybe we can do it once in open + + b) we never know if inputs are synced and zero them if not, + except we use the control interface to check for, but this is + a systemcall we cannot afford in RT Loops so we just don't + and if not it will click... users fault ;-))) + +*/ + +int alsamm_send_dacs(void) +{ + + static double timenow,timelast; + + t_sample *fpo, *fpi, *fp1, *fp2; + int i, err, devno; + + const snd_pcm_channel_area_t *my_areas; + snd_pcm_sframes_t size; + snd_pcm_sframes_t commitres; + snd_pcm_state_t state; + snd_pcm_sframes_t ooffset, oavail; + snd_pcm_sframes_t ioffset, iavail; + + /* + unused channels should be zeroed out on startup (open) and stay this + */ + int inchannels = STUFF->st_inchannels; + int outchannels = STUFF->st_outchannels; + + timelast = sys_getrealtime(); + +#ifdef ALSAMM_DEBUG + if(dac_send++ < 0) + post("dac send called in %d, out %d, xrun %d",inchannels,outchannels, alsamm_xruns); + + if(alsamm_xruns && (alsamm_xruns % 1000) == 0) + post("1000 xruns accoured"); + + if(dac_send < WATCH_PERIODS){ + out_cm[dac_send] = -1; + in_avail[dac_send] = out_avail[dac_send] = -1; + in_offset[dac_send] = out_offset[dac_send] = -1; + outaddr[dac_send] = inaddr[dac_send] = NULL; + xruns_watch[dac_send] = alsamm_xruns; + } +#endif + + if (!inchannels && !outchannels) + { + return SENDDACS_NO; + } + + /* here we should check if in and out samples are here. + but, the point is if out samples available also in sample should, + so we don't make a precheck of insamples here and let outsample check be the + the first of the forst card. + */ + + + /* OUTPUT Transfer */ + fpo = STUFF->st_soundout; + for(devno = 0;devno < alsa_noutdev;devno++){ + + t_alsa_dev *dev = &alsa_outdev[devno]; + snd_pcm_t *out = dev->a_handle; + int ochannels =dev->a_channels; + + + + /* how much samples available ??? */ + oavail = snd_pcm_avail_update(out); + + /* only one reason i can think about, + the driver stopped and says broken pipe + so this should not happen if we have enough stopthreshhold + but if try to restart with next commit + */ + if (oavail < 0) { + +#ifdef ALSAMM_DEBUG + broken_opipe++; +#endif + err = xrun_recovery(out, -EPIPE); + if (err < 0) { + check_error(err,"otavail<0 recovery failed"); + return SENDDACS_NO; + } + oavail = snd_pcm_avail_update(out); + } + + /* check if we are late and have to (able to) catch up */ + /* xruns will be ignored since you cant do anything since already happened */ + state = snd_pcm_state(out); + if (state == SND_PCM_STATE_XRUN) { + err = xrun_recovery(out, -EPIPE); + if (err < 0) { + check_error(err,"DAC XRUN recovery failed"); + return SENDDACS_NO; + } + oavail = snd_pcm_avail_update(out); + + } else if (state == SND_PCM_STATE_SUSPENDED) { + err = xrun_recovery(out, -ESTRPIPE); + if (err < 0) { + check_error(err,"DAC SUSPEND recovery failed"); + return SENDDACS_NO; + } + oavail = snd_pcm_avail_update(out); + } + +#ifdef ALSAMM_DEBUG + if(dac_send < WATCH_PERIODS){ + out_avail[dac_send] = oavail; + } +#endif + + /* we only transfer transfersize of bytes request, + this should only happen on first card otherwise we got a problem :-(()*/ + + if(oavail < alsamm_transfersize){ + return SENDDACS_NO; + } + + /* transfer now */ + size = alsamm_transfersize; + fp1 = fpo; + ooffset = 0; + + /* since this can go over a buffer boundery we maybe need two steps to + transfer (normally when buffersize is a multiple of transfersize + this should never happen) */ + + while (size > 0) { + + int chn; + snd_pcm_sframes_t oframes; + + oframes = size; + + err = alsamm_get_channels(out, (unsigned long *)&oframes, + (unsigned long *)&ooffset,ochannels,dev->a_addr); + +#ifdef ALSAMM_DEBUG + if(dac_send < WATCH_PERIODS){ + out_offset[dac_send] = ooffset; + outaddr[dac_send] = (char *) dev->a_addr[0]; + } +#endif + + if (err < 0){ + if ((err = xrun_recovery(out, err)) < 0) { + check_error(err,"MMAP begins avail error"); + break; /* next card please */ + } + } + + /* transfer into memory */ + for (chn = 0; chn < ochannels; chn++) { + + t_alsa_sample32 *buf = (t_alsa_sample32 *)dev->a_addr[chn]; + + /* + osc(buf, oframes, (dac_send%1000 < 500)?-100.0:-10.0,440,&(indexes[chn])); + */ + + for (i = 0, fp2 = fp1 + chn*alsamm_transfersize; i < oframes; i++,fp2++) + { + float s1 = *fp2 * F32MAX; + /* better but slower, better never clip ;-) + buf[i]= CLIP32(s1); */ + buf[i]= ((int) s1 & 0xFFFFFF00); + *fp2 = 0.0; + } + } + + commitres = snd_pcm_mmap_commit(out, ooffset, oframes); + if (commitres < 0 || commitres != oframes) { + if ((err = xrun_recovery(out, commitres >= 0 ? -EPIPE : commitres)) < 0) { + check_error(err,"MMAP commit error"); + return SENDDACS_NO; + } + } + +#ifdef ALSAMM_DEBUG + if(dac_send < WATCH_PERIODS) + out_cm[dac_send] = oframes; +#endif + + fp1 += oframes; + size -= oframes; + } /* while size */ + fpo += ochannels*alsamm_transfersize; + + }/* for devno */ + + + fpi = STUFF->st_soundin; /* star first card first channel */ + + for(devno = 0;devno < alsa_nindev;devno++){ + + t_alsa_dev *dev = &alsa_indev[devno]; + snd_pcm_t *in = dev->a_handle; + int ichannels = dev->a_channels; + + iavail = snd_pcm_avail_update(in); + + if (iavail < 0) { + err = xrun_recovery(in, iavail); + if (err < 0) { + check_error(err,"input avail update failed"); + return SENDDACS_NO; + } + iavail=snd_pcm_avail_update(in); + } + + state = snd_pcm_state(in); + + if (state == SND_PCM_STATE_XRUN) { + err = xrun_recovery(in, -EPIPE); + if (err < 0) { + check_error(err,"ADC XRUN recovery failed"); + return SENDDACS_NO; + } + iavail=snd_pcm_avail_update(in); + + } else if (state == SND_PCM_STATE_SUSPENDED) { + err = xrun_recovery(in, -ESTRPIPE); + if (err < 0) { + check_error(err,"ADC SUSPEND recovery failed"); + return SENDDACS_NO; + } + iavail=snd_pcm_avail_update(in); + } + + /* only transfer full transfersize or nothing */ + if(iavail < alsamm_transfersize){ + return SENDDACS_NO; + } + size = alsamm_transfersize; + fp1 = fpi; + ioffset = 0; + + /* since sysdata can go over a driver buffer boundery we maybe need two steps to + transfer (normally when buffersize is a multiple of transfersize + this should never happen) */ + + while(size > 0){ + int chn; + snd_pcm_sframes_t iframes = size; + + err = alsamm_get_channels(in, + (unsigned long *)&iframes, (unsigned long *)&ioffset,ichannels,dev->a_addr); + if (err < 0){ + if ((err = xrun_recovery(in, err)) < 0) { + check_error(err,"MMAP begins avail error"); + return SENDDACS_NO; + } + } + +#ifdef ALSAMM_DEBUG + if(dac_send < WATCH_PERIODS){ + in_avail[dac_send] = iavail; + in_offset[dac_send] = ioffset; + inaddr[dac_send] = dev->a_addr[0]; + } +#endif + /* transfer into memory */ + + for (chn = 0; chn < ichannels; chn++) { + + t_alsa_sample32 *buf = (t_alsa_sample32 *) dev->a_addr[chn]; + + for (i = 0, fp2 = fp1 + chn*alsamm_transfersize; i < iframes; i++,fp2++) + { + /* mask the lowest bits, since subchannels info can make zero samples nonzero */ + *fp2 = (float) ((t_alsa_sample32) (buf[i] & 0xFFFFFF00)) + * (1.0 / (float) INT32_MAX); + } + } + + commitres = snd_pcm_mmap_commit(in, ioffset, iframes); + if (commitres < 0 || commitres != iframes) { + post("please never"); + if ((err = xrun_recovery(in, commitres >= 0 ? -EPIPE : commitres)) < 0) { + check_error(err,"MMAP synced in commit error"); + return SENDDACS_NO; + } + } + fp1 += iframes; + size -= iframes; + } + fpi += ichannels*alsamm_transfersize; + } /* for out devno < alsamm_outcards*/ + + + if ((timenow = sys_getrealtime()) > (timelast + sleep_time)) + { + +#ifdef ALSAMM_DEBUG + if(dac_send < 10 && sys_verbose) + post("slept %f > %f + %f (=%f)", + timenow,timelast,sleep_time,(timelast + sleep_time)); +#endif + return (SENDDACS_SLEPT); + } + + return SENDDACS_YES; +} + + +/* extra debug info */ + +void alsamm_showstat(snd_pcm_t *handle) +{ + int err; + snd_pcm_status_t *status; + snd_output_t *output = NULL; + + snd_pcm_status_alloca(&status); + if ((err = snd_pcm_status(handle, status)) < 0) { + check_error(err, "Get Stream status error"); + return; + } + snd_pcm_status_dump(status, alsa_stdout); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_audio_audiounit.c b/ports/camomile/source/LibPd/pure-data/src/s_audio_audiounit.c new file mode 100644 index 00000000..6510bc71 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_audio_audiounit.c @@ -0,0 +1,43 @@ + +/* ------------- routines for Apple AudioUnit in AudioToolbox -------------- */ +#ifdef USEAPI_AUDIOUNIT + +/* this is currently a placeholder file while we decide which one of three implementations of this API we use */ + +#include +#include +#include +#include "m_pd.h" +#include "s_stuff.h" +#include + +pthread_mutex_t audiounit_mutex; +pthread_cond_t audiounit_sem; + +int audiounit_open_audio(int inchans, int outchans, int rate) +{ + return 0; +} + +void audiounit_close_audio(void) +{ +} + +int audiounit_send_dacs(void) +{ + return 0; +} + +void audiounit_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize) +{ + post("device getting not implemented for AudioUnit yet\n"); +} + +void audiounit_listdevs( void) +{ + post("device listing not implemented for AudioUnit yet\n"); +} + +#endif /* AUDIOUNIT */ diff --git a/ports/camomile/source/LibPd/pure-data/src/s_audio_dummy.c b/ports/camomile/source/LibPd/pure-data/src/s_audio_dummy.c new file mode 100644 index 00000000..2543bb3e --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_audio_dummy.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2010 Peter Brinkmann (peter.brinkmann@gmail.com) + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + +#ifdef USEAPI_DUMMY + +#include + +int dummy_open_audio(int nin, int nout, int sr) { + return 0; +} + +int dummy_close_audio( void) { + return 0; +} + +int dummy_send_dacs( void) { + return 0; +} + +void dummy_getdevs(char *indevlist, int *nindevs, char *outdevlist, + int *noutdevs, int *canmulti, int maxndev, int devdescsize) { + sprintf(indevlist, "NONE"); + sprintf(outdevlist, "NONE"); + *nindevs = *noutdevs = 1; + *canmulti = 0; +} + +void dummy_listdevs( void) { + // do nothing +} + +#endif + diff --git a/ports/camomile/source/LibPd/pure-data/src/s_audio_esd.c b/ports/camomile/source/LibPd/pure-data/src/s_audio_esd.c new file mode 100644 index 00000000..652d8af6 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_audio_esd.c @@ -0,0 +1,132 @@ +/* Copyright (c) 2006 Guenter Geiger, +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifdef USEAPI_ESD + +#include +#include /* memset */ +#include +#include "m_pd.h" +#include "s_stuff.h" +#include "m_fixed.h" + +/* exported variables */ + +/* private data */ + +static int esd_socket_out; +static int esd_channels_out; + +static int esd_socket_in; +static int esd_channels_in; + + +int esd_open_audio(int nindev, int *indev, int nchin, int *chin, + int noutdev, int *outdev, int nchout, int *chout, int rate) +{ + + esd_format_t format = ESD_BITS16 | ESD_STEREO | ESD_STREAM | ESD_PLAY; + + indev[0] = 0; + nindev = 1; + + outdev[0] = 0; + noutdev = 1; + + rate = sys_dacsr = ESD_DEFAULT_RATE; + + if (*chout == 2) { + esd_socket_out = esd_play_stream_fallback(format, ESD_DEFAULT_RATE, NULL, "pd"); + if (esd_socket_out <= 0) { + fprintf (stderr, "Error at esd open: %d\n", esd_socket_out); + esd_channels_out = *chout = 0; + return 0; + } + esd_channels_out = *chout = 2; + } + + if (*chin == 2) { + esd_socket_in = esd_record_stream_fallback(format, ESD_DEFAULT_RATE, NULL, "pd-in"); + if (esd_socket_in <= 0) { + fprintf (stderr, "Error at esd open: %d\n", esd_socket_in); + esd_channels_in = *chin = 0; + return 0; + } + esd_channels_in = *chin = 2; + } + return (0); +} + +void esd_close_audio( void) +{ + close(esd_socket_out); + close(esd_socket_in); +} + + +#define DEFDACBLKSIZE 64 +#define MAXCHANS 2 + +static short buf[DEFDACBLKSIZE*MAXCHANS]; + +int esd_send_dacs(void) +{ + t_sample* fp1,*fp2; + short* sp; + int i,j; + + /* Do input */ + + if (esd_channels_in) { + read(esd_socket_in,buf,DEFDACBLKSIZE*esd_channels_out*2); + for (i = DEFDACBLKSIZE, fp1 = sys_soundin, + sp = (short *)buf; i--; fp1++, sp += esd_channels_in) { + for (j=0, fp2 = fp1; j 32767) s = 32767; + else if (s < -32767) s = -32767; + sp[j] = s; + } + } + + write(esd_socket_out,buf,DEFDACBLKSIZE*esd_channels_out*2); + } + + memset(sys_soundin,0,DEFDACBLKSIZE*esd_channels_out*2); + memset(sys_soundout,0,DEFDACBLKSIZE*esd_channels_out*4); + + return (SENDDACS_YES); +} + +void esd_listdevs( void) +{ + post("device listing not implemented for ESD yet\n"); +} + +void esd_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize) +{ + int i, ndev; + *canmulti = 1; /* supports multiple devices */ + sprintf(indevlist, "ESD device"); + sprintf(outdevlist, "ESD device"); + *nindevs = *noutdevs = 1; +} + +#endif diff --git a/ports/camomile/source/LibPd/pure-data/src/s_audio_jack.c b/ports/camomile/source/LibPd/pure-data/src/s_audio_jack.c new file mode 100644 index 00000000..2907e87d --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_audio_jack.c @@ -0,0 +1,572 @@ +/* Copyright (c) 2003, Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* Audio back-end for connecting with the JACK audio interconnect system. +*/ + +#ifdef USEAPI_JACK + +#include +#include +#include +#include "m_pd.h" +#include "s_stuff.h" +#ifdef __APPLE__ +#include +#endif +#include +#include + +#define MAX_CLIENTS 100 +#define MAX_JACK_PORTS 128 /* higher values seem to give bad xrun problems */ +#define BUF_JACK 4096 +#define JACK_OUT_MAX 64 + +static jack_nframes_t jack_out_max; +static jack_nframes_t jack_filled = 0; +static t_sample *jack_outbuf; +static t_sample *jack_inbuf; +static int jack_started = 0; +static jack_port_t *input_port[MAX_JACK_PORTS]; +static jack_port_t *output_port[MAX_JACK_PORTS]; +static int outport_count = 0; +static jack_client_t *jack_client = NULL; +static char * desired_client_name = NULL; +char *jack_client_names[MAX_CLIENTS]; +static int jack_dio_error; +static t_audiocallback jack_callback; +static int jack_should_autoconnect = 1; +pthread_mutex_t jack_mutex; +pthread_cond_t jack_sem; + +static int pollprocess(jack_nframes_t nframes, void *arg) +{ + int j; + jack_default_audio_sample_t *out, *in; + + pthread_mutex_lock(&jack_mutex); + if (nframes > JACK_OUT_MAX) jack_out_max = nframes; + else jack_out_max = JACK_OUT_MAX; + if (jack_filled >= nframes) + { + if (jack_filled != nframes) + fprintf(stderr,"Partial read\n"); + /* hmm, how to find out whether 't_sample' and + 'jack_default_audio_sample_t' are actually the same type??? */ + if (sizeof(t_sample)==sizeof(jack_default_audio_sample_t)) + { + for (j = 0; j < STUFF->st_outchannels; j++) + { + if (out = jack_port_get_buffer(output_port[j], nframes)) + memcpy(out, jack_outbuf + (j * BUF_JACK), + sizeof (jack_default_audio_sample_t) * nframes); + } + for (j = 0; j < STUFF->st_inchannels; j++) + { + if (in = jack_port_get_buffer(input_port[j], nframes)) + memcpy(jack_inbuf + (j * BUF_JACK), in, + sizeof (jack_default_audio_sample_t) * nframes); + } + } + else + { + unsigned int frame=0; + t_sample*data; + for (j = 0; j < STUFF->st_outchannels; j++) + { + if (out = jack_port_get_buffer (output_port[j], nframes)) + { + data = jack_outbuf + (j * BUF_JACK); + for (frame=0; framest_inchannels; j++) + { + if (in = jack_port_get_buffer( input_port[j], nframes)) + { + data = jack_inbuf + (j * BUF_JACK); + for (frame=0; framest_inchannels; chan++) + in[chan] = jack_port_get_buffer(input_port[chan], nframes); + for (chan = 0; chan < STUFF->st_outchannels; chan++) + out[chan] = jack_port_get_buffer(output_port[chan], nframes); + for (n = 0; n < nframes; n += DEFDACBLKSIZE) + { + t_sample *fp; + for (chan = 0; chan < STUFF->st_inchannels; chan++) + if (in[chan]) + { + for (fp = STUFF->st_soundin + chan*DEFDACBLKSIZE, + jp = in[chan] + n, j=0; j < DEFDACBLKSIZE; j++) + *fp++ = *jp++; + } + for (chan = 0; chan < STUFF->st_outchannels; chan++) + { + for (fp = STUFF->st_soundout + chan*DEFDACBLKSIZE, + j = 0; j < DEFDACBLKSIZE; j++) + *fp++ = 0; + } + (*jack_callback)(); + for (chan = 0; chan < STUFF->st_outchannels; chan++) + if (out[chan]) + { + for (fp = STUFF->st_soundout + chan*DEFDACBLKSIZE, jp = out[chan] + n, + j=0; j < DEFDACBLKSIZE; j++) + *jp++ = *fp++; + } + } + return 0; +} + +static int +jack_srate (jack_nframes_t srate, void *arg) +{ + STUFF->st_dacsr = srate; + return 0; +} + + +void glob_audio_setapi(void *dummy, t_floatarg f); + +static void +jack_shutdown (void *arg) +{ + error("JACK: server shut down"); + + jack_deactivate (jack_client); + //jack_client_close(jack_client); /* likely to hang if the server shut down */ + jack_client = NULL; + + glob_audio_setapi(NULL, API_NONE); // set pd_whichapi 0 +} + +static int jack_xrun(void* arg) { + jack_dio_error = 1; + return 0; +} + + +static char** jack_get_clients(void) +{ + const char **jack_ports; + int i,j; + int num_clients = 0; + regex_t port_regex; + jack_ports = jack_get_ports( jack_client, "", "", 0 ); + regcomp( &port_regex, "^[^:]*", REG_EXTENDED ); + + jack_client_names[0] = NULL; + + /* Build a list of clients from the list of ports */ + for( i = 0; jack_ports[i] != NULL; i++ ) + { + int client_seen; + regmatch_t match_info; + char tmp_client_name[100]; + + if(num_clients>=MAX_CLIENTS)break; + + + /* extract the client name from the port name, using a regex + * that parses the clientname:portname syntax */ + regexec( &port_regex, jack_ports[i], 1, &match_info, 0 ); + memcpy( tmp_client_name, &jack_ports[i][match_info.rm_so], + match_info.rm_eo - match_info.rm_so ); + tmp_client_name[ match_info.rm_eo - match_info.rm_so ] = '\0'; + + /* do we know about this port's client yet? */ + client_seen = 0; + + for( j = 0; j < num_clients; j++ ) + if( strcmp( tmp_client_name, jack_client_names[j] ) == 0 ) + client_seen = 1; + + if( client_seen == 0 ) + { + jack_client_names[num_clients] = (char*)getbytes(strlen(tmp_client_name) + 1); + + /* The alsa_pcm client should go in spot 0. If this + * is the alsa_pcm client AND we are NOT about to put + * it in spot 0 put it in spot 0 and move whatever + * was already in spot 0 to the end. */ + + if( strcmp( "alsa_pcm", tmp_client_name ) == 0 && num_clients > 0 ) + { + char* tmp; + /* alsa_pcm goes in spot 0 */ + tmp = jack_client_names[ num_clients ]; + jack_client_names[ num_clients ] = jack_client_names[0]; + jack_client_names[0] = tmp; + strcpy( jack_client_names[0], tmp_client_name); + } + else + { + /* put the new client at the end of the client list */ + strcpy( jack_client_names[ num_clients ], tmp_client_name ); + } + num_clients++; + } + } + + /* for (i=0;i 96) return -1; + + sprintf( regex_pattern, "%s:.*", client ); + + jack_ports = jack_get_ports( jack_client, regex_pattern, + NULL, JackPortIsOutput); + if (jack_ports) + { + for (i=0;jack_ports[i] != NULL && i < STUFF->st_inchannels;i++) + if (jack_connect (jack_client, jack_ports[i], + jack_port_name (input_port[i]))) + error ("JACK: cannot connect input ports %s -> %s", + jack_ports[i],jack_port_name (input_port[i])); + free(jack_ports); + } + jack_ports = jack_get_ports( jack_client, regex_pattern, + NULL, JackPortIsInput); + if (jack_ports) + { + for (i=0;jack_ports[i] != NULL && i < STUFF->st_outchannels;i++) + if (jack_connect (jack_client, jack_port_name (output_port[i]), + jack_ports[i])) + error( "JACK: cannot connect output ports %s -> %s", + jack_port_name (output_port[i]),jack_ports[i]); + + free(jack_ports); + } + return 0; +} + + +static void pd_jack_error_callback(const char *desc) { + error("JACKerror: %s", desc); + return; +} + +int +jack_open_audio(int inchans, int outchans, int rate, t_audiocallback callback) +{ + int j; + char port_name[80] = ""; + char client_name[80] = ""; + + int client_iterator = 0; + int new_jack = 0; + int srate; + jack_status_t status; + + if (!jack_client_open) + { + error("Can't open Jack (it seems not to be installed)"); + return 1; + } + + jack_dio_error = 0; + + if ((inchans == 0) && (outchans == 0)) return 0; + + if (outchans > MAX_JACK_PORTS) { + error("JACK: %d output ports not supported, setting to %d", + outchans, MAX_JACK_PORTS); + outchans = MAX_JACK_PORTS; + } + + if (inchans > MAX_JACK_PORTS) { + error("JACK: %d input ports not supported, setting to %d", + inchans, MAX_JACK_PORTS); + inchans = MAX_JACK_PORTS; + } + + /* try to become a client of the JACK server. (If no JACK server exists, + jack_client_open() will start uone up by default. It's not clear + whether or not this is desirable; see long Pd list thread started by + yvan volochine, June 2013) */ + if (!jack_client) { + if (!desired_client_name || !strlen(desired_client_name)) + jack_client_name("pure_data"); + jack_client = jack_client_open (desired_client_name, JackNoStartServer, + &status, NULL); + if (status & JackFailure) { + error("JACK: Failure. Is JACK running?"); + verbose(1, "JACK: Returned status is: %d", status); + jack_client=NULL; + /* jack spits out enough messages already, do not warn */ + STUFF->st_inchannels = STUFF->st_outchannels = 0; + return 1; + } + if (status & JackNameNotUnique) + jack_client_name(jack_get_client_name(jack_client)); + verbose(1, "JACK: registered as '%s'", desired_client_name); + + STUFF->st_inchannels = inchans; + STUFF->st_outchannels = outchans; + if (jack_inbuf) + free(jack_inbuf); + if (STUFF->st_inchannels) + jack_inbuf = calloc(sizeof(t_sample), STUFF->st_inchannels * BUF_JACK); + if (jack_outbuf) + free(jack_outbuf); + if (STUFF->st_outchannels) + jack_outbuf = calloc(sizeof(t_sample), STUFF->st_outchannels * BUF_JACK); + + jack_get_clients(); + + /* set JACK callback functions */ + + jack_callback = callback; + jack_set_process_callback(jack_client, + (callback? callbackprocess : pollprocess), 0); + + jack_set_error_function (pd_jack_error_callback); + +#ifdef JACK_XRUN + jack_set_xrun_callback (jack_client, jack_xrun, NULL); +#endif + + /* tell the JACK server to call `srate()' whenever + the sample rate of the system changes. + */ + + jack_set_sample_rate_callback (jack_client, jack_srate, 0); + + + /* tell the JACK server to call `jack_shutdown()' if + it ever shuts down, either entirely, or if it + just decides to stop calling us. + */ + + jack_on_shutdown (jack_client, jack_shutdown, 0); + + for (j=0; jst_inchannels; j++) + input_port[j]=NULL; + for (j=0; jst_outchannels; j++) + output_port[j] = NULL; + + new_jack = 1; + } + + /* display the current sample rate. once the client is activated + (see below), you should rely on your own sample rate + callback (see above) for this value. + */ + + srate = jack_get_sample_rate (jack_client); + STUFF->st_dacsr = srate; + + /* create the ports */ + + for (j = 0; j < inchans; j++) + { + sprintf(port_name, "input%d", j); + if (!input_port[j]) input_port[j] = jack_port_register (jack_client, + port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); + if (!input_port[j]) + { + error("JACK: can only register %d input ports (of %d requested)", + j, inchans); + STUFF->st_inchannels = inchans = j; + break; + } + } + + for (j = 0; j < outchans; j++) + { + sprintf(port_name, "output%d", j); + if (!output_port[j]) output_port[j] = jack_port_register (jack_client, + port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + if (!output_port[j]) + { + error("JACK: can only register %d output ports (of %d requested)", + j, outchans); + STUFF->st_outchannels = outchans = j; + break; + } + } + outport_count = outchans; + + /* tell the JACK server that we are ready to roll */ + + if (new_jack) + { + if (jack_activate (jack_client)) { + error("cannot activate client"); + STUFF->st_inchannels = STUFF->st_outchannels = 0; + return 1; + } + + for (j = 0; j < outchans; j++) + memset(jack_outbuf + j * BUF_JACK, 0, + BUF_JACK * sizeof(t_sample)); + + if (jack_client_names[0] && jack_should_autoconnect) + jack_connect_ports(jack_client_names[0]); + + pthread_mutex_init(&jack_mutex, NULL); + pthread_cond_init(&jack_sem, NULL); + } + return 0; +} + +void jack_close_audio(void) +{ + if (jack_client){ + jack_deactivate (jack_client); + jack_client_close(jack_client); + } + + jack_client=NULL; + jack_started = 0; + + pthread_cond_broadcast(&jack_sem); + + pthread_cond_destroy(&jack_sem); + pthread_mutex_destroy(&jack_mutex); + if (jack_inbuf) + free(jack_inbuf), jack_inbuf = 0; + if (jack_outbuf) + free(jack_outbuf), jack_outbuf = 0; + +} + +int jack_send_dacs(void) +{ + t_sample * fp; + int j; + int rtnval = SENDDACS_YES; + int timenow; + int timeref = sys_getrealtime(); + if (!jack_client) return SENDDACS_NO; + if (!STUFF->st_inchannels && !STUFF->st_outchannels) return (SENDDACS_NO); + if (jack_dio_error) + { + sys_log_error(ERR_RESYNC); + jack_dio_error = 0; + } + pthread_mutex_lock(&jack_mutex); + if (jack_filled >= jack_out_max) + pthread_cond_wait(&jack_sem,&jack_mutex); + + if (!jack_client) + { + pthread_mutex_unlock(&jack_mutex); + return SENDDACS_NO; + } + jack_started = 1; + + fp = STUFF->st_soundout; + for (j = 0; j < STUFF->st_outchannels; j++) + { + memcpy(jack_outbuf + (j * BUF_JACK) + jack_filled, fp, + DEFDACBLKSIZE*sizeof(t_sample)); + fp += DEFDACBLKSIZE; + } + fp = STUFF->st_soundin; + for (j = 0; j < STUFF->st_inchannels; j++) + { + memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled, + DEFDACBLKSIZE*sizeof(t_sample)); + fp += DEFDACBLKSIZE; + } + jack_filled += DEFDACBLKSIZE; + pthread_mutex_unlock(&jack_mutex); + + if ((timenow = sys_getrealtime()) - timeref > 0.002) + { + rtnval = SENDDACS_SLEPT; + } + memset(STUFF->st_soundout, 0, DEFDACBLKSIZE*sizeof(t_sample)*STUFF->st_outchannels); + return rtnval; +} + +void jack_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize) +{ + int i, ndev; + *canmulti = 0; /* supports multiple devices */ + ndev = 1; + for (i = 0; i < ndev; i++) + { + sprintf(indevlist + i * devdescsize, "JACK"); + sprintf(outdevlist + i * devdescsize, "JACK"); + } + *nindevs = *noutdevs = ndev; +} + +void jack_listdevs( void) +{ + post("device listing not implemented for jack yet\n"); +} + +void jack_autoconnect(int v) +{ + jack_should_autoconnect = v; +} + +void jack_client_name(char *name) +{ + if (desired_client_name) { + free(desired_client_name); + desired_client_name = NULL; + } + if (name) { + desired_client_name = (char*)getbytes(strlen(name) + 1); + strcpy(desired_client_name, name); + } +} + +#endif /* JACK */ diff --git a/ports/camomile/source/LibPd/pure-data/src/s_audio_mmio.c b/ports/camomile/source/LibPd/pure-data/src/s_audio_mmio.c new file mode 100644 index 00000000..e1b5946a --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_audio_mmio.c @@ -0,0 +1,794 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* modified 2/98 by Winfried Ritsch to deal with up to 4 synchronized +"wave" devices, which is how ADAT boards appear to the WAVE API. */ + +#include "m_pd.h" +#include "s_stuff.h" +#include + +#include + +#include + +/* ------------------------- audio -------------------------- */ + +static void nt_close_midiin(void); +static void nt_noresync( void); + +static void postflags(void); + +#define NAPORTS 16 /* wini hack for multiple ADDA devices */ +#define CHANNELS_PER_DEVICE 2 +#define DEFAULTCHANS 2 +#define DEFAULTSRATE 44100 +#define SAMPSIZE 2 + +int nt_realdacblksize; +#define DEFREALDACBLKSIZE (4 * DEFDACBLKSIZE) /* larger underlying bufsize */ + +#define MAXBUFFER 100 /* number of buffers in use at maximum advance */ +#define DEFBUFFER 30 /* default is about 30x6 = 180 msec! */ +static int nt_naudiobuffer = DEFBUFFER; + +static int nt_whichapi = API_MMIO; +static int nt_meters; /* true if we're metering */ +static float nt_inmax; /* max input amplitude */ +static float nt_outmax; /* max output amplitude */ +static int nt_nwavein, nt_nwaveout; /* number of WAVE devices in and out */ + +typedef struct _sbuf +{ + HANDLE hData; + HPSTR lpData; // pointer to waveform data memory + HANDLE hWaveHdr; + WAVEHDR *lpWaveHdr; // pointer to header structure +} t_sbuf; + +t_sbuf ntsnd_outvec[NAPORTS][MAXBUFFER]; /* circular buffer array */ +HWAVEOUT ntsnd_outdev[NAPORTS]; /* output device */ +static int ntsnd_outphase[NAPORTS]; /* index of next buffer to send */ + +t_sbuf ntsnd_invec[NAPORTS][MAXBUFFER]; /* circular buffer array */ +HWAVEIN ntsnd_indev[NAPORTS]; /* input device */ +static int ntsnd_inphase[NAPORTS]; /* index of next buffer to read */ + +static void nt_waveinerror(char *s, int err) +{ + char t[256]; + waveInGetErrorText(err, t, 256); + fprintf(stderr, s, t); +} + +static void nt_waveouterror(char *s, int err) +{ + char t[256]; + waveOutGetErrorText(err, t, 256); + fprintf(stderr, s, t); +} + +static void wave_prep(t_sbuf *bp, int setdone) +{ + WAVEHDR *wh; + short *sp; + int i; + /* + * Allocate and lock memory for the waveform data. The memory + * for waveform data must be globally allocated with + * GMEM_MOVEABLE and GMEM_SHARE flags. + */ + + if (!(bp->hData = + GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, + (DWORD) (CHANNELS_PER_DEVICE * SAMPSIZE * nt_realdacblksize)))) + printf("alloc 1 failed\n"); + + if (!(bp->lpData = + (HPSTR) GlobalLock(bp->hData))) + printf("lock 1 failed\n"); + + /* Allocate and lock memory for the header. */ + + if (!(bp->hWaveHdr = + GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (DWORD) sizeof(WAVEHDR)))) + printf("alloc 2 failed\n"); + + if (!(wh = bp->lpWaveHdr = + (WAVEHDR *) GlobalLock(bp->hWaveHdr))) + printf("lock 2 failed\n"); + + for (i = CHANNELS_PER_DEVICE * nt_realdacblksize, + sp = (short *)bp->lpData; i--; ) + *sp++ = 0; + + wh->lpData = bp->lpData; + wh->dwBufferLength = (CHANNELS_PER_DEVICE * SAMPSIZE * nt_realdacblksize); + wh->dwFlags = 0; + wh->dwLoops = 0L; + wh->lpNext = 0; + wh->reserved = 0; + /* optionally (for writing) set DONE flag as if we had queued them */ + if (setdone) + wh->dwFlags = WHDR_DONE; +} + +static UINT nt_whichdac = WAVE_MAPPER, nt_whichadc = WAVE_MAPPER; + +int mmio_do_open_audio(void) +{ + PCMWAVEFORMAT form; + int i, j; + UINT mmresult; + int nad, nda; + static int naudioprepped = 0, nindevsprepped = 0, noutdevsprepped = 0; + if (sys_verbose) + post("%d devices in, %d devices out", + nt_nwavein, nt_nwaveout); + + form.wf.wFormatTag = WAVE_FORMAT_PCM; + form.wf.nChannels = CHANNELS_PER_DEVICE; + form.wf.nSamplesPerSec = STUFF->st_dacsr; + form.wf.nAvgBytesPerSec = STUFF->st_dacsr * (CHANNELS_PER_DEVICE * SAMPSIZE); + form.wf.nBlockAlign = CHANNELS_PER_DEVICE * SAMPSIZE; + form.wBitsPerSample = 8 * SAMPSIZE; + + if (nt_nwavein <= 1 && nt_nwaveout <= 1) + nt_noresync(); + + if (nindevsprepped < nt_nwavein) + { + for (i = nindevsprepped; i < nt_nwavein; i++) + for (j = 0; j < naudioprepped; j++) + wave_prep(&ntsnd_invec[i][j], 0); + nindevsprepped = nt_nwavein; + } + if (noutdevsprepped < nt_nwaveout) + { + for (i = noutdevsprepped; i < nt_nwaveout; i++) + for (j = 0; j < naudioprepped; j++) + wave_prep(&ntsnd_outvec[i][j], 1); + noutdevsprepped = nt_nwaveout; + } + if (naudioprepped < nt_naudiobuffer) + { + for (j = naudioprepped; j < nt_naudiobuffer; j++) + { + for (i = 0; i < nt_nwavein; i++) + wave_prep(&ntsnd_invec[i][j], 0); + for (i = 0; i < nt_nwaveout; i++) + wave_prep(&ntsnd_outvec[i][j], 1); + } + naudioprepped = nt_naudiobuffer; + } + for (nad=0; nad < nt_nwavein; nad++) + { + /* Open waveform device(s), sucessively numbered, for input */ + + mmresult = waveInOpen(&ntsnd_indev[nad], nt_whichadc+nad, + (WAVEFORMATEX *)(&form), 0L, 0L, CALLBACK_NULL); + + if (sys_verbose) + printf("opened adc device %d with return %d\n", + nt_whichadc+nad,mmresult); + + if (mmresult != MMSYSERR_NOERROR) + { + nt_waveinerror("waveInOpen: %s\n", mmresult); + nt_nwavein = nad; /* nt_nwavein = 0 wini */ + } + else + { + for (i = 0; i < nt_naudiobuffer; i++) + { + mmresult = waveInPrepareHeader(ntsnd_indev[nad], + ntsnd_invec[nad][i].lpWaveHdr, sizeof(WAVEHDR)); + if (mmresult != MMSYSERR_NOERROR) + nt_waveinerror("waveinprepareheader: %s\n", mmresult); + mmresult = waveInAddBuffer(ntsnd_indev[nad], + ntsnd_invec[nad][i].lpWaveHdr, sizeof(WAVEHDR)); + if (mmresult != MMSYSERR_NOERROR) + nt_waveinerror("waveInAddBuffer: %s\n", mmresult); + } + } + } + /* quickly start them all together */ + for (nad = 0; nad < nt_nwavein; nad++) + waveInStart(ntsnd_indev[nad]); + + for (nda = 0; nda < nt_nwaveout; nda++) + { + /* Open a waveform device for output in sucessiv device numbering*/ + mmresult = waveOutOpen(&ntsnd_outdev[nda], nt_whichdac + nda, + (WAVEFORMATEX *)(&form), 0L, 0L, CALLBACK_NULL); + + if (sys_verbose) + fprintf(stderr,"opened dac device %d, with return %d\n", + nt_whichdac +nda, mmresult); + + if (mmresult != MMSYSERR_NOERROR) + { + fprintf(stderr,"Wave out open device %d + %d\n",nt_whichdac,nda); + nt_waveouterror("waveOutOpen device: %s\n", mmresult); + nt_nwaveout = nda; + } + } + + return (0); +} + +void mmio_close_audio( void) +{ + int errcode; + int nda, nad; + if (sys_verbose) + post("closing audio..."); + + for (nda=0; nda < nt_nwaveout; nda++) /*if (nt_nwaveout) wini */ + { + errcode = waveOutReset(ntsnd_outdev[nda]); + if (errcode != MMSYSERR_NOERROR) + printf("error resetting output %d: %d\n", nda, errcode); + errcode = waveOutClose(ntsnd_outdev[nda]); + if (errcode != MMSYSERR_NOERROR) + printf("error closing output %d: %d\n",nda , errcode); + } + nt_nwaveout = 0; + + for(nad=0; nad < nt_nwavein;nad++) /* if (nt_nwavein) wini */ + { + errcode = waveInReset(ntsnd_indev[nad]); + if (errcode != MMSYSERR_NOERROR) + printf("error resetting input: %d\n", errcode); + errcode = waveInClose(ntsnd_indev[nad]); + if (errcode != MMSYSERR_NOERROR) + printf("error closing input: %d\n", errcode); + } + nt_nwavein = 0; +} + + +#define ADCJITTER 10 /* We tolerate X buffers of jitter by default */ +#define DACJITTER 10 + +static int nt_adcjitterbufsallowed = ADCJITTER; +static int nt_dacjitterbufsallowed = DACJITTER; + + /* ------------- MIDI time stamping from audio clock ------------ */ + +#ifdef MIDI_TIMESTAMP + +static double nt_hibuftime; +static double initsystime = -1; + + /* call this whenever we reset audio */ +static void nt_resetmidisync(void) +{ + initsystime = clock_getsystime(); + nt_hibuftime = sys_getrealtime(); +} + + /* call this whenever we're idled waiting for audio to be ready. + The routine maintains a high and low water point for the difference + between real and DAC time. */ + +static void nt_midisync(void) +{ + double jittersec, diff; + + if (initsystime == -1) nt_resetmidisync(); + jittersec = (nt_dacjitterbufsallowed > nt_adcjitterbufsallowed ? + nt_dacjitterbufsallowed : nt_adcjitterbufsallowed) + * nt_realdacblksize / STUFF->st_getsr(); + diff = sys_getrealtime() - 0.001 * clock_gettimesince(initsystime); + if (diff > nt_hibuftime) nt_hibuftime = diff; + if (diff < nt_hibuftime - jittersec) + { + post("jitter excess %d %f", dac, diff); + nt_resetmidisync(); + } +} + +static double nt_midigettimefor(LARGE_INTEGER timestamp) +{ + /* this is broken now... used to work when "timestamp" was derived from + QueryPerformanceCounter() instead of the gates approved + timeGetSystemTime() call in the MIDI callback routine below. */ + return (nt_tixtotime(timestamp) - nt_hibuftime); +} +#endif /* MIDI_TIMESTAMP */ + + +static int nt_fill = 0; +#define WRAPFWD(x) ((x) >= nt_naudiobuffer ? (x) - nt_naudiobuffer: (x)) +#define WRAPBACK(x) ((x) < 0 ? (x) + nt_naudiobuffer: (x)) +#define MAXRESYNC 500 + +#if 0 /* this is used for debugging */ +static void nt_printaudiostatus(void) +{ + int nad, nda; + for (nad = 0; nad < nt_nwavein; nad++) + { + int phase = ntsnd_inphase[nad]; + int phase2 = phase, phase3 = WRAPFWD(phase2), count, ntrans = 0; + int firstphasedone = -1, firstphasebusy = -1; + for (count = 0; count < nt_naudiobuffer; count++) + { + int donethis = + (ntsnd_invec[nad][phase2].lpWaveHdr->dwFlags & WHDR_DONE); + int donenext = + (ntsnd_invec[nad][phase3].lpWaveHdr->dwFlags & WHDR_DONE); + if (donethis && !donenext) + { + if (firstphasebusy >= 0) goto multipleadc; + firstphasebusy = count; + } + if (!donethis && donenext) + { + if (firstphasedone >= 0) goto multipleadc; + firstphasedone = count; + } + phase2 = phase3; + phase3 = WRAPFWD(phase2 + 1); + } + post("nad %d phase %d busy %d done %d", nad, phase, firstphasebusy, + firstphasedone); + continue; + multipleadc: + startpost("nad %d phase %d: oops:", nad, phase); + for (count = 0; count < nt_naudiobuffer; count++) + { + char buf[80]; + sprintf(buf, " %d", + (ntsnd_invec[nad][count].lpWaveHdr->dwFlags & WHDR_DONE)); + poststring(buf); + } + endpost(); + } + for (nda = 0; nda < nt_nwaveout; nda++) + { + int phase = ntsnd_outphase[nad]; + int phase2 = phase, phase3 = WRAPFWD(phase2), count, ntrans = 0; + int firstphasedone = -1, firstphasebusy = -1; + for (count = 0; count < nt_naudiobuffer; count++) + { + int donethis = + (ntsnd_outvec[nda][phase2].lpWaveHdr->dwFlags & WHDR_DONE); + int donenext = + (ntsnd_outvec[nda][phase3].lpWaveHdr->dwFlags & WHDR_DONE); + if (donethis && !donenext) + { + if (firstphasebusy >= 0) goto multipledac; + firstphasebusy = count; + } + if (!donethis && donenext) + { + if (firstphasedone >= 0) goto multipledac; + firstphasedone = count; + } + phase2 = phase3; + phase3 = WRAPFWD(phase2 + 1); + } + if (firstphasebusy < 0) post("nda %d phase %d all %d", + nda, phase, (ntsnd_outvec[nad][0].lpWaveHdr->dwFlags & WHDR_DONE)); + else post("nda %d phase %d busy %d done %d", nda, phase, firstphasebusy, + firstphasedone); + continue; + multipledac: + startpost("nda %d phase %d: oops:", nda, phase); + for (count = 0; count < nt_naudiobuffer; count++) + { + char buf[80]; + sprintf(buf, " %d", + (ntsnd_outvec[nad][count].lpWaveHdr->dwFlags & WHDR_DONE)); + poststring(buf); + } + endpost(); + } +} +#endif /* 0 */ + +/* this is a hack to avoid ever resyncing audio pointers in case for whatever +reason the sync testing below gives false positives. */ + +static int nt_resync_cancelled; + +static void nt_noresync( void) +{ + nt_resync_cancelled = 1; +} + +static void nt_resyncaudio(void) +{ + UINT mmresult; + int nad, nda, count; + if (nt_resync_cancelled) + return; + /* for each open input device, eat all buffers which are marked + ready. The next one will thus be "busy". */ + post("resyncing audio"); + for (nad = 0; nad < nt_nwavein; nad++) + { + int phase = ntsnd_inphase[nad]; + for (count = 0; count < MAXRESYNC; count++) + { + WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr; + if (!(inwavehdr->dwFlags & WHDR_DONE)) break; + if (inwavehdr->dwFlags & WHDR_PREPARED) + waveInUnprepareHeader(ntsnd_indev[nad], + inwavehdr, sizeof(WAVEHDR)); + inwavehdr->dwFlags = 0L; + waveInPrepareHeader(ntsnd_indev[nad], inwavehdr, sizeof(WAVEHDR)); + mmresult = waveInAddBuffer(ntsnd_indev[nad], inwavehdr, + sizeof(WAVEHDR)); + if (mmresult != MMSYSERR_NOERROR) + nt_waveinerror("waveInAddBuffer: %s\n", mmresult); + ntsnd_inphase[nad] = phase = WRAPFWD(phase + 1); + } + if (count == MAXRESYNC) post("resync error 1"); + } + /* Each output buffer which is "ready" is filled with zeros and + queued. */ + for (nda = 0; nda < nt_nwaveout; nda++) + { + int phase = ntsnd_outphase[nda]; + for (count = 0; count < MAXRESYNC; count++) + { + WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr; + if (!(outwavehdr->dwFlags & WHDR_DONE)) break; + if (outwavehdr->dwFlags & WHDR_PREPARED) + waveOutUnprepareHeader(ntsnd_outdev[nda], + outwavehdr, sizeof(WAVEHDR)); + outwavehdr->dwFlags = 0L; + memset((char *)(ntsnd_outvec[nda][phase].lpData), + 0, (CHANNELS_PER_DEVICE * SAMPSIZE * nt_realdacblksize)); + waveOutPrepareHeader(ntsnd_outdev[nda], outwavehdr, + sizeof(WAVEHDR)); + mmresult = waveOutWrite(ntsnd_outdev[nda], outwavehdr, + sizeof(WAVEHDR)); + if (mmresult != MMSYSERR_NOERROR) + nt_waveouterror("waveOutAddBuffer: %s\n", mmresult); + ntsnd_outphase[nda] = phase = WRAPFWD(phase + 1); + } + if (count == MAXRESYNC) post("resync error 2"); + } + +#ifdef MIDI_TIMESTAMP + nt_resetmidisync(); +#endif + +} + +#define LATE 0 +#define RESYNC 1 +#define NOTHING 2 +static int nt_errorcount; +static int nt_resynccount; +static double nt_nextreporttime = -1; + +void nt_logerror(int which) +{ +#if 0 + post("error %d %d", count, which); + if (which < NOTHING) nt_errorcount++; + if (which == RESYNC) nt_resynccount++; + if (sys_getrealtime() > nt_nextreporttime) + { + post("%d audio I/O error%s", nt_errorcount, + (nt_errorcount > 1 ? "s" : "")); + if (nt_resynccount) post("DAC/ADC sync error"); + nt_errorcount = nt_resynccount = 0; + nt_nextreporttime = sys_getrealtime() - 5; + } +#endif +} + +/* system buffer with t_sample types for one tick */ + +int mmio_send_dacs(void) +{ + HMMIO hmmio; + UINT mmresult; + HANDLE hFormat; + int i, j; + short *sp1, *sp2; + float *fp1, *fp2; + int nextfill, doxfer = 0; + int nda, nad; + if (!nt_nwavein && !nt_nwaveout) return (0); + + + if (nt_meters) + { + int i, n; + float maxsamp; + for (i = 0, n = 2 * nt_nwavein * DEFDACBLKSIZE, maxsamp = nt_inmax; + i < n; i++) + { + float f = STUFF->st_soundin[i]; + if (f > maxsamp) maxsamp = f; + else if (-f > maxsamp) maxsamp = -f; + } + nt_inmax = maxsamp; + for (i = 0, n = 2 * nt_nwaveout * DEFDACBLKSIZE, maxsamp = nt_outmax; + i < n; i++) + { + float f = STUFF->st_soundout[i]; + if (f > maxsamp) maxsamp = f; + else if (-f > maxsamp) maxsamp = -f; + } + nt_outmax = maxsamp; + } + + /* the "fill pointer" nt_fill controls where in the next + I/O buffers we will write and/or read. If it's zero, we + first check whether the buffers are marked "done". */ + + if (!nt_fill) + { + for (nad = 0; nad < nt_nwavein; nad++) + { + int phase = ntsnd_inphase[nad]; + WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr; + if (!(inwavehdr->dwFlags & WHDR_DONE)) goto idle; + } + for (nda = 0; nda < nt_nwaveout; nda++) + { + int phase = ntsnd_outphase[nda]; + WAVEHDR *outwavehdr = + ntsnd_outvec[nda][phase].lpWaveHdr; + if (!(outwavehdr->dwFlags & WHDR_DONE)) goto idle; + } + for (nad = 0; nad < nt_nwavein; nad++) + { + int phase = ntsnd_inphase[nad]; + WAVEHDR *inwavehdr = + ntsnd_invec[nad][phase].lpWaveHdr; + if (inwavehdr->dwFlags & WHDR_PREPARED) + waveInUnprepareHeader(ntsnd_indev[nad], + inwavehdr, sizeof(WAVEHDR)); + } + for (nda = 0; nda < nt_nwaveout; nda++) + { + int phase = ntsnd_outphase[nda]; + WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr; + if (outwavehdr->dwFlags & WHDR_PREPARED) + waveOutUnprepareHeader(ntsnd_outdev[nda], + outwavehdr, sizeof(WAVEHDR)); + } + } + + /* Convert audio output to fixed-point and put it in the output + buffer. */ + for (nda = 0, fp1 = STUFF->st_soundout; nda < nt_nwaveout; nda++) + { + int phase = ntsnd_outphase[nda]; + + for (i = 0, sp1 = (short *)(ntsnd_outvec[nda][phase].lpData) + + CHANNELS_PER_DEVICE * nt_fill; + i < 2; i++, fp1 += DEFDACBLKSIZE, sp1++) + { + for (j = 0, fp2 = fp1, sp2 = sp1; j < DEFDACBLKSIZE; + j++, fp2++, sp2 += CHANNELS_PER_DEVICE) + { + int x1 = 32767.f * *fp2; + if (x1 > 32767) x1 = 32767; + else if (x1 < -32767) x1 = -32767; + *sp2 = x1; + } + } + } + memset(STUFF->st_soundout, 0, + (DEFDACBLKSIZE *sizeof(t_sample)*CHANNELS_PER_DEVICE)*nt_nwaveout); + + /* vice versa for the input buffer */ + + for (nad = 0, fp1 = STUFF->st_soundin; nad < nt_nwavein; nad++) + { + int phase = ntsnd_inphase[nad]; + + for (i = 0, sp1 = (short *)(ntsnd_invec[nad][phase].lpData) + + CHANNELS_PER_DEVICE * nt_fill; + i < 2; i++, fp1 += DEFDACBLKSIZE, sp1++) + { + for (j = 0, fp2 = fp1, sp2 = sp1; j < DEFDACBLKSIZE; + j++, fp2++, sp2 += CHANNELS_PER_DEVICE) + { + *fp2 = ((float)(1./32767.)) * (float)(*sp2); + } + } + } + + nt_fill = nt_fill + DEFDACBLKSIZE; + if (nt_fill == nt_realdacblksize) + { + nt_fill = 0; + + for (nad = 0; nad < nt_nwavein; nad++) + { + int phase = ntsnd_inphase[nad]; + HWAVEIN device = ntsnd_indev[nad]; + WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr; + waveInPrepareHeader(device, inwavehdr, sizeof(WAVEHDR)); + mmresult = waveInAddBuffer(device, inwavehdr, sizeof(WAVEHDR)); + if (mmresult != MMSYSERR_NOERROR) + nt_waveinerror("waveInAddBuffer: %s\n", mmresult); + ntsnd_inphase[nad] = WRAPFWD(phase + 1); + } + for (nda = 0; nda < nt_nwaveout; nda++) + { + int phase = ntsnd_outphase[nda]; + HWAVEOUT device = ntsnd_outdev[nda]; + WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr; + waveOutPrepareHeader(device, outwavehdr, sizeof(WAVEHDR)); + mmresult = waveOutWrite(device, outwavehdr, sizeof(WAVEHDR)); + if (mmresult != MMSYSERR_NOERROR) + nt_waveouterror("waveOutWrite: %s\n", mmresult); + ntsnd_outphase[nda] = WRAPFWD(phase + 1); + } + + /* check for DAC underflow or ADC overflow. */ + for (nad = 0; nad < nt_nwavein; nad++) + { + int phase = WRAPBACK(ntsnd_inphase[nad] - 2); + WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr; + if (inwavehdr->dwFlags & WHDR_DONE) goto late; + } + for (nda = 0; nda < nt_nwaveout; nda++) + { + int phase = WRAPBACK(ntsnd_outphase[nda] - 2); + WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr; + if (outwavehdr->dwFlags & WHDR_DONE) goto late; + } + } + return (1); + +late: + + nt_logerror(LATE); + nt_resyncaudio(); + return (1); + +idle: + + /* If more than nt_adcjitterbufsallowed ADC buffers are ready + on any input device, resynchronize */ + + for (nad = 0; nad < nt_nwavein; nad++) + { + int phase = ntsnd_inphase[nad]; + WAVEHDR *inwavehdr = + ntsnd_invec[nad] + [WRAPFWD(phase + nt_adcjitterbufsallowed)].lpWaveHdr; + if (inwavehdr->dwFlags & WHDR_DONE) + { + nt_resyncaudio(); + return (0); + } + } + + /* test dac sync the same way */ + for (nda = 0; nda < nt_nwaveout; nda++) + { + int phase = ntsnd_outphase[nda]; + WAVEHDR *outwavehdr = + ntsnd_outvec[nda] + [WRAPFWD(phase + nt_dacjitterbufsallowed)].lpWaveHdr; + if (outwavehdr->dwFlags & WHDR_DONE) + { + nt_resyncaudio(); + return (0); + } + } +#ifdef MIDI_TIMESTAMP + nt_midisync(); +#endif + return (0); +} + +/* ------------------- public routines -------------------------- */ + +int mmio_open_audio(int naudioindev, int *audioindev, + int nchindev, int *chindev, int naudiooutdev, int *audiooutdev, + int nchoutdev, int *choutdev, int rate, int blocksize) +{ + int nbuf; + + nt_realdacblksize = (blocksize ? blocksize : DEFREALDACBLKSIZE); + nbuf = sys_advance_samples/nt_realdacblksize; + if (nbuf >= MAXBUFFER) + { + fprintf(stderr, "pd: audio buffering maxed out to %d\n", + (int)(MAXBUFFER * ((nt_realdacblksize * 1000.)/44100.))); + nbuf = MAXBUFFER; + } + else if (nbuf < 4) nbuf = 4; + /* fprintf(stderr, "%d audio buffers\n", nbuf); */ + nt_naudiobuffer = nbuf; + if (nt_adcjitterbufsallowed > nbuf - 2) + nt_adcjitterbufsallowed = nbuf - 2; + if (nt_dacjitterbufsallowed > nbuf - 2) + nt_dacjitterbufsallowed = nbuf - 2; + + nt_nwavein = STUFF->st_inchannels / 2; + nt_nwaveout = STUFF->st_outchannels / 2; + nt_whichadc = (naudioindev < 1 ? + (nt_nwavein > 1 ? WAVE_MAPPER : -1) : audioindev[0]); + nt_whichdac = (naudiooutdev < 1 ? + (nt_nwaveout > 1 ? WAVE_MAPPER : -1) : audiooutdev[0]); + if (naudiooutdev > 1 || naudioindev > 1) + post("separate audio device choice not supported; using sequential devices."); + return (mmio_do_open_audio()); +} + + +void mmio_reportidle(void) +{ +} + +#if 0 +/* list the audio and MIDI device names */ +void mmio_listdevs(void) +{ + UINT wRtn, ndevices; + unsigned int i; + + ndevices = waveInGetNumDevs(); + for (i = 0; i < ndevices; i++) + { + WAVEINCAPS wicap; + wRtn = waveInGetDevCaps(i, (LPWAVEINCAPS) &wicap, + sizeof(wicap)); + if (wRtn) nt_waveinerror("waveInGetDevCaps: %s\n", wRtn); + else fprintf(stderr, + "audio input device #%d: %s\n", i+1, wicap.szPname); + } + + ndevices = waveOutGetNumDevs(); + for (i = 0; i < ndevices; i++) + { + WAVEOUTCAPS wocap; + wRtn = waveOutGetDevCaps(i, (LPWAVEOUTCAPS) &wocap, + sizeof(wocap)); + if (wRtn) nt_waveouterror("waveOutGetDevCaps: %s\n", wRtn); + else fprintf(stderr, + "audio output device #%d: %s\n", i+1, wocap.szPname); + } +} +#endif + +void mmio_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize) +{ + int wRtn, ndev, i; + + *canmulti = 2; /* supports multiple devices */ + ndev = waveInGetNumDevs(); + if (ndev > maxndev) + ndev = maxndev; + *nindevs = ndev; + for (i = 0; i < ndev; i++) + { + WAVEINCAPS wicap; + wRtn = waveInGetDevCaps(i, (LPWAVEINCAPS) &wicap, sizeof(wicap)); + _snprintf(indevlist + i * devdescsize, devdescsize, "%s", + (wRtn ? "???" : wicap.szPname)); + outdevlist[(i+1) * devdescsize - 1] = 0; + } + + ndev = waveOutGetNumDevs(); + if (ndev > maxndev) + ndev = maxndev; + *noutdevs = ndev; + for (i = 0; i < ndev; i++) + { + WAVEOUTCAPS wocap; + wRtn = waveOutGetDevCaps(i, (LPWAVEOUTCAPS) &wocap, sizeof(wocap)); + _snprintf(outdevlist + i * devdescsize, devdescsize, "%s", + (wRtn ? "???" : wocap.szPname)); + outdevlist[(i+1) * devdescsize - 1] = 0; + } +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_audio_oss.c b/ports/camomile/source/LibPd/pure-data/src/s_audio_oss.c new file mode 100644 index 00000000..c597f076 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_audio_oss.c @@ -0,0 +1,795 @@ +/* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler, +* Winfried Ritsch, Karl MacMillan, and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* this file inputs and outputs audio using the OSS API available on linux. */ + +#include + +#ifndef SNDCTL_DSP_GETISPACE +#define SNDCTL_DSP_GETISPACE SOUND_PCM_GETISPACE +#endif +#ifndef SNDCTL_DSP_GETOSPACE +#define SNDCTL_DSP_GETOSPACE SOUND_PCM_GETOSPACE +#endif + +#include "m_pd.h" +#include "s_stuff.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Defines */ +#define DEBUG(x) x +#define DEBUG2(x) {x;} + +#define OSS_MAXCHPERDEV 32 /* max channels per OSS device */ +#define OSS_MAXDEV 4 /* maximum number of input or output devices */ +#define OSS_DEFFRAGSIZE 256 /* default log fragment size (frames) */ +#define OSS_DEFAUDIOBUF 40000 /* default audiobuffer, microseconds */ +#define OSS_DEFAULTCH 2 +#define RME_DEFAULTCH 8 /* need this even if RME undefined */ +typedef int16_t t_oss_int16; +typedef int32_t t_oss_int32; +#define OSS_MAXSAMPLEWIDTH sizeof(t_oss_int32) +#define OSS_BYTESPERCHAN(width) (DEFDACBLKSIZE * (width)) +#define OSS_XFERSAMPS(chans) (DEFDACBLKSIZE* (chans)) +#define OSS_XFERSIZE(chans, width) (DEFDACBLKSIZE * (chans) * (width)) + +/* GLOBALS */ +static int linux_meters; /* true if we're metering */ +static t_sample linux_inmax; /* max input amplitude */ +static t_sample linux_outmax; /* max output amplitude */ +static int linux_fragsize = 0; /* for block mode; block size (sample frames) */ +extern int audio_blocksize; /* stolen from s_audio.c */ +/* our device handles */ + +typedef struct _oss_dev +{ + int d_fd; + unsigned int d_space; /* bytes available for writing/reading */ + int d_bufsize; /* total buffer size in blocks for this device */ + int d_dropcount; /* # of buffers to drop for resync (output only) */ + unsigned int d_nchannels; /* number of channels for this device */ + unsigned int d_bytespersamp; /* bytes per sample (2 for 16 bit, 4 for 32) */ +} t_oss_dev; + +static t_oss_dev linux_dacs[OSS_MAXDEV]; +static t_oss_dev linux_adcs[OSS_MAXDEV]; +static int linux_noutdevs = 0; +static int linux_nindevs = 0; + + /* OSS-specific private variables */ +static int oss_blockmode = 1; /* flag to use "blockmode" */ +static char ossdsp[] = "/dev/dsp%d"; + + /* don't assume we can turn all 31 bits when doing float-to-fix; + otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. */ +#define FMAX 0x7ffff000 +#define CLIP32(x) (((x)>FMAX)?FMAX:((x) < -FMAX)?-FMAX:(x)) + +/* ---------------- public routines ----------------------- */ + +static int oss_ndev = 0; + + /* find out how many OSS devices we have. Since this has to + open the devices to find out if they're there, we have + to be called before audio is actually started up. So we + cache the results, which in effect are the number of available + devices. */ +void oss_init(void) +{ + int fd, i; + static int countedthem = 0; + if (countedthem) + return; + for (i = 0; i < 10; i++) + { + char devname[100]; + if (i == 0) + strcpy(devname, "/dev/dsp"); + else sprintf(devname, "/dev/dsp%d", i); + if ( (fd = open(devname, O_WRONLY|O_NONBLOCK)) != -1) + { + oss_ndev++; + close(fd); + } + else break; + } + countedthem = 1; +} + +typedef struct _multidev { + int fd; + int channels; + int format; +} t_multidev; + +int oss_reset(int fd) { + int err; + if ((err = ioctl(fd,SNDCTL_DSP_RESET)) < 0) + error("OSS: Could not reset"); + return err; +} + +void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize, + int suggestedblocksize) +{ + int orig, param, nblk, fd = dev->d_fd, wantformat; + int nchannels = dev->d_nchannels; + int advwas = sys_schedadvance; + + audio_buf_info ainfo; + + /* we only know how to do 2 byte samples */ + wantformat = AFMT_S16_NE; + dev->d_bytespersamp = 2; + + param = wantformat; + + if (ioctl(fd, SNDCTL_DSP_SETFMT, ¶m) == -1) + fprintf(stderr,"OSS: Could not set DSP format\n"); + else if (wantformat != param) + fprintf(stderr,"OSS: DSP format: wanted %d, got %d\n", + wantformat, param); + + /* sample rate */ + orig = param = srate; + if (ioctl(fd, SNDCTL_DSP_SPEED, ¶m) == -1) + fprintf(stderr,"OSS: Could not set sampling rate for device\n"); + else if( orig != param ) + fprintf(stderr,"OSS: sampling rate: wanted %d, got %d\n", + orig, param ); + + if (oss_blockmode && !skipblocksize) + { + int fragbytes, logfragsize, nfragment; + /* setting fragment count and size. */ + linux_fragsize = suggestedblocksize; + if (!linux_fragsize) + { + linux_fragsize = OSS_DEFFRAGSIZE; + while (linux_fragsize > DEFDACBLKSIZE + && linux_fragsize * 6 > sys_advance_samples) + linux_fragsize = linux_fragsize/2; + } + /* post("adv_samples %d", sys_advance_samples); */ + nfragment = (sys_schedadvance * (44100. * 1.e-6)) / linux_fragsize; + + fragbytes = linux_fragsize * (dev->d_bytespersamp * nchannels); + logfragsize = ilog2(fragbytes); + + if (fragbytes != (1 << logfragsize)) + post("warning: OSS takes only power of 2 blocksize; using %d", + (1 << logfragsize)/(dev->d_bytespersamp * nchannels)); + if (sys_verbose) + post("setting nfrags = %d, fragsize %d\n", nfragment, fragbytes); + + param = orig = (nfragment<<16) + logfragsize; + if (ioctl(fd,SNDCTL_DSP_SETFRAGMENT, ¶m) == -1) + error("OSS: Could not set or read fragment size\n"); + if (param != orig) + { + nfragment = ((param >> 16) & 0xffff); + logfragsize = (param & 0xffff); + post("warning: actual fragments %d, blocksize %d", + nfragment, (1 << logfragsize)); + } + if (sys_verbose) + post("audiobuffer set to %d msec", (int)(0.001 * sys_schedadvance)); + } + + if (dac) + { + /* use "free space" to learn the buffer size. Normally you + should set this to your own desired value; but this seems not + to be implemented uniformly across different sound cards. LATER + we should figure out what to do if the requested scheduler advance + is greater than this buffer size; for now, we just print something + out. */ + + int defect; + if (ioctl(fd, SNDCTL_DSP_GETOSPACE,&ainfo) < 0) + fprintf(stderr,"OSS: ioctl on output device failed"); + dev->d_bufsize = ainfo.bytes; + + defect = sys_advance_samples * (dev->d_bytespersamp * nchannels) + - dev->d_bufsize - OSS_XFERSIZE(nchannels, dev->d_bytespersamp); + if (defect > 0) + { + if (sys_verbose || defect > (dev->d_bufsize >> 2)) + fprintf(stderr, + "OSS: requested audio buffer size %d limited to %d\n", + sys_advance_samples * (dev->d_bytespersamp * nchannels), + dev->d_bufsize); + sys_advance_samples = + (dev->d_bufsize - OSS_XFERSAMPS(nchannels)) / + (dev->d_bytespersamp *nchannels); + } + } +} + +static int oss_setchannels(int fd, int wantchannels, char *devname) +{ + int param; + if (sys_verbose) + post("setchan %d", wantchannels); + if (ioctl(fd, SNDCTL_DSP_CHANNELS, ¶m) == -1) + { + if (sys_verbose) + error("OSS: SOUND_DSP_READ_CHANNELS failed %s", devname); + } + else + { + if (sys_verbose) + post("channels originally %d for %s", param, devname); + if (param == wantchannels) + { + if (sys_verbose) + post("number of channels doesn't need setting\n"); + return (wantchannels); + } + } + param = wantchannels; +whynot: + while (param > 1) + { + int save = param; + if (ioctl(fd, SNDCTL_DSP_CHANNELS, ¶m) == -1) + error("OSS: SNDCTL_DSP_CHANNELS failed %s",devname); + else if (param == save) + return (param); + param = save - 1; + } + + return (0); +} + +int oss_open_audio(int nindev, int *indev, int nchin, int *chin, + int noutdev, int *outdev, int nchout, int *chout, int rate, + int blocksize) +{ + int capabilities = 0; + int inchannels = 0, outchannels = 0; + char devname[20]; + int n, i, fd, flags; + char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV]; + int num_devs = 0; + int wantmore=0; + int spread = 0; + audio_buf_info ainfo; + + linux_nindevs = linux_noutdevs = 0; + /* mark devices unopened */ + for (i = 0; i < OSS_MAXDEV; i++) + linux_adcs[i].d_fd = linux_dacs[i].d_fd = -1; + + /* open output devices */ + wantmore=0; + if (noutdev < 0 || nindev < 0) + bug("linux_open_audio"); + + for (n = 0; n < noutdev; n++) + { + int gotchans, j, inindex = -1; + int thisdevice = (outdev[n] >= 0 ? outdev[n] : 0); + int wantchannels = (nchout>n) ? chout[n] : wantmore; + fd = -1; + if (!wantchannels) + goto end_out_loop; + + if (thisdevice > 0) + sprintf(devname, "/dev/dsp%d", thisdevice); + else sprintf(devname, "/dev/dsp"); + /* search for input request for same device. Succeed only + if the number of channels matches. */ + for (j = 0; j < nindev; j++) + if (indev[j] == thisdevice && chin[j] == wantchannels) + inindex = j; + + /* if the same device is requested for input and output, + try to open it read/write */ + if (inindex >= 0) + { + sys_setalarm(1000000); + if ((fd = open(devname, O_RDWR | O_NDELAY)) == -1) + { + post("%s (read/write): %s", devname, strerror(errno)); + post("(now will try write-only...)"); + } + else + { + if (fcntl(fd, F_SETFD, 1) < 0) + post("couldn't set close-on-exec flag on audio"); + if ((flags = fcntl(fd, F_GETFL)) < 0) + post("couldn't get audio device flags"); + else if (fcntl(fd, F_SETFL, flags & (~O_NDELAY)) < 0) + post("couldn't set audio device flags"); + if (sys_verbose) + post("opened %s for reading and writing\n", devname); + linux_adcs[inindex].d_fd = fd; + } + } + /* if that didn't happen or if it failed, try write-only */ + if (fd == -1) + { + sys_setalarm(1000000); + if ((fd = open(devname, O_WRONLY | O_NDELAY)) == -1) + { + post("%s (writeonly): %s", + devname, strerror(errno)); + break; + } + if (fcntl(fd, F_SETFD, 1) < 0) + post("couldn't set close-on-exec flag on audio"); + if ((flags = fcntl(fd, F_GETFL)) < 0) + post("couldn't get audio device flags"); + else if (fcntl(fd, F_SETFL, flags & (~O_NDELAY)) < 0) + post("couldn't set audio device flags"); + if (sys_verbose) + post("opened %s for writing only\n", devname); + } + if (ioctl(fd, SNDCTL_DSP_GETCAPS, &capabilities) == -1) + error("OSS: SNDCTL_DSP_GETCAPS failed %s", devname); + + gotchans = oss_setchannels(fd, + (wantchannels>OSS_MAXCHPERDEV)?OSS_MAXCHPERDEV:wantchannels, + devname); + + if (sys_verbose) + post("opened audio output on %s; got %d channels", + devname, gotchans); + + if (gotchans < 2) + { + /* can't even do stereo? just give up. */ + close(fd); + } + else + { + linux_dacs[linux_noutdevs].d_nchannels = gotchans; + linux_dacs[linux_noutdevs].d_fd = fd; + oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0, blocksize); + + linux_noutdevs++; + outchannels += gotchans; + if (inindex >= 0) + { + linux_adcs[inindex].d_nchannels = gotchans; + chin[inindex] = gotchans; + } + } + /* LATER think about spreading large numbers of channels over + various dsp's and vice-versa */ + wantmore = wantchannels - gotchans; + end_out_loop: ; + } + + /* open input devices */ + wantmore = 0; + for (n = 0; n < nindev; n++) + { + int gotchans=0; + int thisdevice = (indev[n] >= 0 ? indev[n] : 0); + int wantchannels = (nchin>n)?chin[n]:wantmore; + int alreadyopened = 0; + if (!wantchannels) + goto end_in_loop; + + if (thisdevice > 0) + sprintf(devname, "/dev/dsp%d", thisdevice); + else sprintf(devname, "/dev/dsp"); + + sys_setalarm(1000000); + + /* perhaps it's already open from the above? */ + if (linux_adcs[n].d_fd >= 0) + { + fd = linux_adcs[n].d_fd; + alreadyopened = 1; + if (sys_verbose) + post("already opened it"); + } + else + { + /* otherwise try to open it here. */ + if ((fd = open(devname, O_RDONLY | O_NDELAY)) == -1) + { + post("%s (readonly): %s", devname, strerror(errno)); + goto end_in_loop; + } + if (fcntl(fd, F_SETFD, 1) < 0) + post("couldn't set close-on-exec flag on audio"); + if ((flags = fcntl(fd, F_GETFL)) < 0) + post("couldn't get audio device flags"); + else if (fcntl(fd, F_SETFL, flags & (~O_NDELAY)) < 0) + post("couldn't set audio device flags"); + if (sys_verbose) + post("opened %s for reading only\n", devname); + } + linux_adcs[linux_nindevs].d_fd = fd; + + gotchans = oss_setchannels(fd, + (wantchannels>OSS_MAXCHPERDEV)?OSS_MAXCHPERDEV:wantchannels, + devname); + if (sys_verbose) + post("opened audio input device %s; got %d channels", + devname, gotchans); + + if (gotchans < 1) + { + close(fd); + goto end_in_loop; + } + + linux_adcs[linux_nindevs].d_nchannels = gotchans; + + oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened, + blocksize); + + inchannels += gotchans; + linux_nindevs++; + + wantmore = wantchannels-gotchans; + /* LATER think about spreading large numbers of channels over + various dsp's and vice-versa */ + end_in_loop: ; + } + + /* We have to do a read to start the engine. This is + necessary because sys_send_dacs waits until the input + buffer is filled and only reads on a filled buffer. + This is good, because it's a way to make sure that we + will not block. But I wonder why we only have to read + from one of the devices and not all of them??? */ + + if (linux_nindevs) + { + if (sys_verbose) + fprintf(stderr,("OSS: issuing first ADC 'read' ... ")); + read(linux_adcs[0].d_fd, buf, + linux_adcs[0].d_bytespersamp * + linux_adcs[0].d_nchannels * DEFDACBLKSIZE); + if (sys_verbose) + fprintf(stderr, "...done.\n"); + } + /* now go and fill all the output buffers. */ + for (i = 0; i < linux_noutdevs; i++) + { + int j; + memset(buf, 0, linux_dacs[i].d_bytespersamp * + linux_dacs[i].d_nchannels * DEFDACBLKSIZE); + for (j = 0; j < sys_advance_samples/DEFDACBLKSIZE; j++) + write(linux_dacs[i].d_fd, buf, + linux_dacs[i].d_bytespersamp * + linux_dacs[i].d_nchannels * DEFDACBLKSIZE); + } + sys_setalarm(0); + STUFF->st_inchannels = inchannels; + STUFF->st_outchannels = outchannels; + return (0); +} + +void oss_close_audio( void) +{ + int i; + for (i=0;i + OSS_XFERSIZE(linux_adcs[dev].d_nchannels, + linux_adcs[dev].d_bytespersamp)) + { + linux_adcs_read(linux_adcs[dev].d_fd, buf, + OSS_XFERSIZE(linux_adcs[dev].d_nchannels, + linux_adcs[dev].d_bytespersamp)); + if (ioctl(linux_adcs[dev].d_fd, SNDCTL_DSP_GETISPACE, &ainfo) < 0) + { + fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed", + dev, linux_adcs[dev].d_fd); + break; + } + linux_adcs[dev].d_space = ainfo.bytes; + } + } + + /* 2. if any output devices are behind, feed them zeros to catch them + up */ + for (dev = 0; dev < linux_noutdevs; dev++) + { + while (linux_dacs[dev].d_space > linux_dacs[dev].d_bufsize - + sys_advance_samples * (linux_dacs[dev].d_nchannels * + linux_dacs[dev].d_bytespersamp)) + { + if (!zeroed) + { + unsigned int i; + for (i = 0; i < OSS_XFERSAMPS(linux_dacs[dev].d_nchannels); + i++) + buf[i] = 0; + zeroed = 1; + } + linux_dacs_write(linux_dacs[dev].d_fd, buf, + OSS_XFERSIZE(linux_dacs[dev].d_nchannels, + linux_dacs[dev].d_bytespersamp)); + if (ioctl(linux_dacs[dev].d_fd, SNDCTL_DSP_GETOSPACE, &ainfo) < 0) + { + fprintf(stderr, "OSS: ioctl on output device %d, fd %d failed", + dev, linux_dacs[dev].d_fd); + break; + } + linux_dacs[dev].d_space = ainfo.bytes; + } + } + /* 3. if any DAC devices are too far ahead, plan to drop the + number of frames which will let the others catch up. */ + for (dev = 0; dev < linux_noutdevs; dev++) + { + if (linux_dacs[dev].d_space > linux_dacs[dev].d_bufsize - + (sys_advance_samples - 1) * linux_dacs[dev].d_nchannels * + linux_dacs[dev].d_bytespersamp) + { + linux_dacs[dev].d_dropcount = sys_advance_samples - 1 - + (linux_dacs[dev].d_space - linux_dacs[dev].d_bufsize) / + (linux_dacs[dev].d_nchannels * + linux_dacs[dev].d_bytespersamp) ; + } + else linux_dacs[dev].d_dropcount = 0; + } +} + +int oss_send_dacs(void) +{ + t_sample *fp1, *fp2; + long fill; + int i, j, dev, rtnval = SENDDACS_YES; + char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV]; + t_oss_int16 *sp; + t_oss_int32 *lp; + /* the maximum number of samples we should have in the ADC buffer */ + int idle = 0; + int thischan; + double timeref, timenow; + + if (!linux_nindevs && !linux_noutdevs) + return (SENDDACS_NO); + + if (!oss_blockmode) + { + /* determine whether we're idle. This is true if either (1) + some input device has less than one buffer to read or (2) some + output device has fewer than (sys_advance_samples) blocks buffered + already. */ + oss_calcspace(); + + for (dev=0; dev < linux_noutdevs; dev++) + if (linux_dacs[dev].d_dropcount || + (linux_dacs[dev].d_bufsize - linux_dacs[dev].d_space > + sys_advance_samples * linux_dacs[dev].d_bytespersamp * + linux_dacs[dev].d_nchannels)) + idle = 1; + for (dev=0; dev < linux_nindevs; dev++) + if (linux_adcs[dev].d_space < + OSS_XFERSIZE(linux_adcs[dev].d_nchannels, + linux_adcs[dev].d_bytespersamp)) + idle = 1; + } + + if (idle && !oss_blockmode) + { + /* sometimes---rarely---when the ADC available-byte-count is + zero, it's genuine, but usually it's because we're so + late that the ADC has overrun its entire kernel buffer. We + distinguish between the two by waiting 2 msec and asking again. + There should be an error flag we could check instead; look for this + someday... */ + for (dev = 0;dev < linux_nindevs; dev++) + if (linux_adcs[dev].d_space == 0) + { + audio_buf_info ainfo; + sys_microsleep(2000); + oss_calcspace(); + if (linux_adcs[dev].d_space != 0) continue; + + /* here's the bad case. Give up and resync. */ + sys_log_error(ERR_DATALATE); + oss_doresync(); + return (SENDDACS_NO); + } + /* check for slippage between devices, either because + data got lost in the driver from a previous late condition, or + because the devices aren't synced. When we're idle, no + input device should have more than one buffer readable and + no output device should have less than sys_advance_samples-1 + */ + + for (dev=0; dev < linux_noutdevs; dev++) + if (!linux_dacs[dev].d_dropcount && + (linux_dacs[dev].d_bufsize - linux_dacs[dev].d_space < + (sys_advance_samples - 2) * + (linux_dacs[dev].d_bytespersamp * + linux_dacs[dev].d_nchannels))) + goto badsync; + for (dev=0; dev < linux_nindevs; dev++) + if (linux_adcs[dev].d_space > 3 * + OSS_XFERSIZE(linux_adcs[dev].d_nchannels, + linux_adcs[dev].d_bytespersamp)) + goto badsync; + + /* return zero to tell the scheduler we're idle. */ + return (SENDDACS_NO); + badsync: + sys_log_error(ERR_RESYNC); + oss_doresync(); + return (SENDDACS_NO); + + } + + /* do output */ + + timeref = sys_getrealtime(); + for (dev=0, thischan = 0; dev < linux_noutdevs; dev++) + { + int nchannels = linux_dacs[dev].d_nchannels; + if (linux_dacs[dev].d_dropcount) + linux_dacs[dev].d_dropcount--; + else + { + if (linux_dacs[dev].d_bytespersamp == 2) + { + for (i = DEFDACBLKSIZE, fp1 = STUFF->st_soundout + + DEFDACBLKSIZE*thischan, + sp = (t_oss_int16 *)buf; i--; fp1++, sp += nchannels) + { + for (j=0, fp2 = fp1; j 32767) s = 32767; + else if (s < -32767) s = -32767; + sp[j] = s; + } + } + } + linux_dacs_write(linux_dacs[dev].d_fd, buf, + OSS_XFERSIZE(nchannels, linux_dacs[dev].d_bytespersamp)); + if ((timenow = sys_getrealtime()) - timeref > 0.002) + { + if (!oss_blockmode) + sys_log_error(ERR_DACSLEPT); + else rtnval = SENDDACS_SLEPT; + } + timeref = timenow; + } + thischan += nchannels; + } + memset(STUFF->st_soundout, 0, + STUFF->st_outchannels * (sizeof(t_sample) * DEFDACBLKSIZE)); + + /* do input */ + + for (dev = 0, thischan = 0; dev < linux_nindevs; dev++) + { + int nchannels = linux_adcs[dev].d_nchannels; + linux_adcs_read(linux_adcs[dev].d_fd, buf, + OSS_XFERSIZE(nchannels, linux_adcs[dev].d_bytespersamp)); + + if ((timenow = sys_getrealtime()) - timeref > 0.002) + { + if (!oss_blockmode) + sys_log_error(ERR_ADCSLEPT); + else + rtnval = SENDDACS_SLEPT; + } + timeref = timenow; + + if (linux_adcs[dev].d_bytespersamp == 2) + { + for (i = DEFDACBLKSIZE,fp1 = STUFF->st_soundin + thischan*DEFDACBLKSIZE, + sp = (t_oss_int16 *)buf; i--; fp1++, sp += nchannels) + { + for (j=0;j maxndev) + ndev = maxndev; + for (i = 0; i < ndev; i++) + { + sprintf(indevlist + i * devdescsize, "OSS device #%d", i+1); + sprintf(outdevlist + i * devdescsize, "OSS device #%d", i+1); + } + *nindevs = *noutdevs = ndev; +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_audio_pa.c b/ports/camomile/source/LibPd/pure-data/src/s_audio_pa.c new file mode 100644 index 00000000..3ac2f970 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_audio_pa.c @@ -0,0 +1,642 @@ +/* Copyright (c) 2001 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* this file calls Ross Bencina's and Phil Burk's Portaudio package. It's + the main way in for Mac OS and, with Michael Casey's help, also into + ASIO in Windows. + + Both blocking and non-blocking call styles are supported. If non-blocking + is requested, either we call portaudio in non-blocking mode, or else we + call portaudio in callback mode and manage our own FIFO se we can offer + Pd "blocking" I/O calls. To do the latter we define FAKEBLOCKING; this + works better in MAXOSX (gets 40 msec lower latency!) and might also in + Windows. If FAKEBLOCKING is defined we can choose between two methods + for waiting on the (presumebly other-thread) I/O to complete, either + correct thread synchronization (by defining THREADSIGNAL) or just sleeping + and polling; the latter seems to work better so far. +*/ + +/* dolist... + switch to usleep in s_inter.c +*/ + +#include "m_pd.h" +#include "s_stuff.h" +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +#ifndef _WIN32 /* for the "dup2" workaround -- do we still need it? */ +#include +#endif + +#ifdef _WIN32 +# include /* MSVC or mingw on windows */ +#elif defined(__linux__) || defined(__APPLE__) +# include /* linux, mac, mingw, cygwin */ +#else +# include /* BSDs for example */ +#endif + +#if 1 +#define FAKEBLOCKING +#endif + +#if defined (FAKEBLOCKING) && defined(_WIN32) +#include /* for Sleep() */ +#endif + +/* define this to enable thread signaling instead of polling */ +/* #define THREADSIGNAL */ + + /* LATER try to figure out how to handle default devices in portaudio; + the way s_audio.c handles them isn't going to work here. */ + + /* public interface declared in m_imp.h */ + + /* implementation */ +static PaStream *pa_stream; +static int pa_inchans, pa_outchans; +static float *pa_soundin, *pa_soundout; +static t_audiocallback pa_callback; + +static int pa_started; +static int pa_nbuffers; +static int pa_dio_error; + +#ifdef FAKEBLOCKING +#include "s_audio_paring.h" +static PA_VOLATILE char *pa_outbuf; +static PA_VOLATILE sys_ringbuf pa_outring; +static PA_VOLATILE char *pa_inbuf; +static PA_VOLATILE sys_ringbuf pa_inring; +#ifdef THREADSIGNAL +#include +pthread_mutex_t pa_mutex; +pthread_cond_t pa_sem; +#endif /* THREADSIGNAL */ +#endif /* FAKEBLOCKING */ + +static void pa_init(void) /* Initialize PortAudio */ +{ + static int initialized; + if (!initialized) + { +#ifdef __APPLE__ + /* for some reason, on the Mac Pa_Initialize() closes file descriptor + 1 (standard output) As a workaround, dup it to another number and dup2 + it back afterward. */ + int newfd = dup(1); + int another = open("/dev/null", 0); + dup2(another, 1); + int err = Pa_Initialize(); + close(1); + close(another); + if (newfd >= 0) + { + fflush(stdout); + dup2(newfd, 1); + close(newfd); + } +#else + int err = Pa_Initialize(); +#endif + + + if ( err != paNoError ) + { + post("Error opening audio: %s", err, Pa_GetErrorText(err)); + return; + } + initialized = 1; + } +} + +static int pa_lowlevel_callback(const void *inputBuffer, + void *outputBuffer, unsigned long nframes, + const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags myflags, + void *userData) +{ + int i; + unsigned int n, j; + float *fbuf, *fp2, *fp3, *soundiop; + if (nframes % DEFDACBLKSIZE) + { + post("warning: audio nframes %ld not a multiple of blocksize %d", + nframes, (int)DEFDACBLKSIZE); + nframes -= (nframes % DEFDACBLKSIZE); + } + for (n = 0; n < nframes; n += DEFDACBLKSIZE) + { + if (inputBuffer != NULL) + { + fbuf = ((float *)inputBuffer) + n*pa_inchans; + soundiop = pa_soundin; + for (i = 0, fp2 = fbuf; i < pa_inchans; i++, fp2++) + for (j = 0, fp3 = fp2; j < DEFDACBLKSIZE; + j++, fp3 += pa_inchans) + *soundiop++ = *fp3; + } + else memset((void *)pa_soundin, 0, + DEFDACBLKSIZE * pa_inchans * sizeof(float)); + memset((void *)pa_soundout, 0, + DEFDACBLKSIZE * pa_outchans * sizeof(float)); + (*pa_callback)(); + if (outputBuffer != NULL) + { + fbuf = ((float *)outputBuffer) + n*pa_outchans; + soundiop = pa_soundout; + for (i = 0, fp2 = fbuf; i < pa_outchans; i++, fp2++) + for (j = 0, fp3 = fp2; j < DEFDACBLKSIZE; + j++, fp3 += pa_outchans) + *fp3 = *soundiop++; + } + } + return 0; +} + +#ifdef FAKEBLOCKING + /* callback for "non-callback" case in which we actualy open portaudio + in callback mode but fake "blocking mode". We communicate with the + main thread via FIFO. First read the audio output FIFO (which + we sync on, not waiting for it but supplying zeros to the audio output if + there aren't enough samples in the FIFO when we are called), then write + to the audio input FIFO. The main thread will wait for the input fifo. + We can either throw it a pthreads condition or just allow the main thread + to poll for us; so far polling seems to work better. */ +static int pa_fifo_callback(const void *inputBuffer, + void *outputBuffer, unsigned long nframes, + const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags myflags, + void *userData) +{ + /* callback routine for non-callback client... throw samples into + and read them out of a FIFO */ + int ch; + long fiforoom; + float *fbuf; + +#if CHECKFIFOS + if (pa_inchans * sys_ringbuf_getreadavailable(&pa_outring) != + pa_outchans * sys_ringbuf_getwriteavailable(&pa_inring)) + post("warning: in and out rings unequal (%d, %d)", + sys_ringbuf_getreadavailable(&pa_outring), + sys_ringbuf_getwriteavailable(&pa_inring)); +#endif + fiforoom = sys_ringbuf_getreadavailable(&pa_outring); + if ((unsigned)fiforoom >= nframes*pa_outchans*sizeof(float)) + { + if (outputBuffer) + sys_ringbuf_read(&pa_outring, outputBuffer, + nframes*pa_outchans*sizeof(float), pa_outbuf); + else if (pa_outchans) + post("audio error: no outputBuffer but output channels"); + if (inputBuffer) + sys_ringbuf_write(&pa_inring, inputBuffer, + nframes*pa_inchans*sizeof(float), pa_inbuf); + else if (pa_inchans) + post("audio error: no inputBuffer but input channels"); + } + else + { /* PD could not keep up; generate zeros */ + if (pa_started) + pa_dio_error = 1; + if (outputBuffer) + { + for (ch = 0; ch < pa_outchans; ch++) + { + unsigned long frame; + fbuf = ((float *)outputBuffer) + ch; + for (frame = 0; frame < nframes; frame++, fbuf += pa_outchans) + *fbuf = 0; + } + } + } +#ifdef THREADSIGNAL + pthread_mutex_lock(&pa_mutex); + pthread_cond_signal(&pa_sem); + pthread_mutex_unlock(&pa_mutex); +#endif + return 0; +} +#endif /* FAKEBLOCKING */ + +PaError pa_open_callback(double sampleRate, int inchannels, int outchannels, + int framesperbuf, int nbuffers, int indeviceno, int outdeviceno, PaStreamCallback *callbackfn) +{ + long bytesPerSample; + PaError err; + PaStreamParameters instreamparams, outstreamparams; + PaStreamParameters*p_instreamparams=0, *p_outstreamparams=0; + + /* fprintf(stderr, "nchan %d, flags %d, bufs %d, framesperbuf %d\n", + nchannels, flags, nbuffers, framesperbuf); */ + + instreamparams.device = indeviceno; + instreamparams.channelCount = inchannels; + instreamparams.sampleFormat = paFloat32; + instreamparams.hostApiSpecificStreamInfo = 0; + + outstreamparams.device = outdeviceno; + outstreamparams.channelCount = outchannels; + outstreamparams.sampleFormat = paFloat32; + outstreamparams.hostApiSpecificStreamInfo = 0; + +#ifdef FAKEBLOCKING + instreamparams.suggestedLatency = outstreamparams.suggestedLatency = 0; +#else + instreamparams.suggestedLatency = outstreamparams.suggestedLatency = + nbuffers*framesperbuf/sampleRate; +#endif /* FAKEBLOCKING */ + + if( inchannels>0 && indeviceno >= 0) + p_instreamparams=&instreamparams; + if( outchannels>0 && outdeviceno >= 0) + p_outstreamparams=&outstreamparams; + + err=Pa_IsFormatSupported(p_instreamparams, p_outstreamparams, sampleRate); + + if (paFormatIsSupported != err) + { + /* check whether we have to change the numbers of channel and/or samplerate */ + const PaDeviceInfo* info = 0; + double inRate=0, outRate=0; + + if (inchannels>0) + { + if (NULL != (info = Pa_GetDeviceInfo( instreamparams.device ))) + { + inRate=info->defaultSampleRate; + + if(info->maxInputChannelsmaxInputChannels; + } + } + + if (outchannels>0) + { + if (NULL != (info = Pa_GetDeviceInfo( outstreamparams.device ))) + { + outRate=info->defaultSampleRate; + + if(info->maxOutputChannelsmaxOutputChannels; + } + } + + if (err == paInvalidSampleRate) + { + sampleRate=outRate; + } + + err=Pa_IsFormatSupported(p_instreamparams, p_outstreamparams, + sampleRate); + if (paFormatIsSupported != err) + goto error; + } + err = Pa_OpenStream( + &pa_stream, + p_instreamparams, + p_outstreamparams, + sampleRate, + framesperbuf, + paNoFlag, /* portaudio will clip for us */ + callbackfn, + 0); + if (err != paNoError) + goto error; + + err = Pa_StartStream(pa_stream); + if (err != paNoError) + { + post("error opening failed; closing audio stream: %s", + Pa_GetErrorText(err)); + pa_close_audio(); + goto error; + } + STUFF->st_dacsr=sampleRate; + return paNoError; +error: + pa_stream = NULL; + return err; +} + +int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin, + t_sample *soundout, int framesperbuf, int nbuffers, + int indeviceno, int outdeviceno, t_audiocallback callbackfn) +{ + PaError err; + int j, devno, pa_indev = -1, pa_outdev = -1; + + pa_callback = callbackfn; + /* fprintf(stderr, "open callback %d\n", (callbackfn != 0)); */ + pa_init(); + /* post("in %d out %d rate %d device %d", inchans, outchans, rate, deviceno); */ + + if (pa_stream) + pa_close_audio(); + + if (inchans > 0) + { + for (j = 0, devno = 0; j < Pa_GetDeviceCount(); j++) + { + const PaDeviceInfo *info = Pa_GetDeviceInfo(j); + if (info->maxInputChannels > 0) + { + if (devno == indeviceno) + { + if (inchans > info->maxInputChannels) + inchans = info->maxInputChannels; + + pa_indev = j; + break; + } + devno++; + } + } + } + + if (outchans > 0) + { + for (j = 0, devno = 0; j < Pa_GetDeviceCount(); j++) + { + const PaDeviceInfo *info = Pa_GetDeviceInfo(j); + if (info->maxOutputChannels > 0) + { + if (devno == outdeviceno) + { + if (outchans > info->maxOutputChannels) + outchans = info->maxOutputChannels; + + pa_outdev = j; + break; + } + devno++; + } + } + } + + if (inchans > 0 && pa_indev == -1) + inchans = 0; + if (outchans > 0 && pa_outdev == -1) + outchans = 0; + + if (sys_verbose) + { + post("input device %d, channels %d", pa_indev, inchans); + post("output device %d, channels %d", pa_outdev, outchans); + post("framesperbuf %d, nbufs %d", framesperbuf, nbuffers); + post("rate %d", rate); + } + pa_inchans = STUFF->st_inchannels = inchans; + pa_outchans = STUFF->st_outchannels = outchans; + pa_soundin = soundin; + pa_soundout = soundout; + +#ifdef FAKEBLOCKING + if (pa_inbuf) + free((char *)pa_inbuf), pa_inbuf = 0; + if (pa_outbuf) + free((char *)pa_outbuf), pa_outbuf = 0; +#endif + + if (! inchans && !outchans) + return (0); + + if (callbackfn) + { + pa_callback = callbackfn; + err = pa_open_callback(rate, inchans, outchans, + framesperbuf, nbuffers, pa_indev, pa_outdev, pa_lowlevel_callback); + } + else + { +#ifdef FAKEBLOCKING + if (pa_inchans) + { + pa_inbuf = malloc(nbuffers*framesperbuf*pa_inchans*sizeof(float)); + sys_ringbuf_init(&pa_inring, + nbuffers*framesperbuf*pa_inchans*sizeof(float), pa_inbuf, + nbuffers*framesperbuf*pa_inchans*sizeof(float)); + } + if (pa_outchans) + { + pa_outbuf = malloc(nbuffers*framesperbuf*pa_outchans*sizeof(float)); + sys_ringbuf_init(&pa_outring, + nbuffers*framesperbuf*pa_outchans*sizeof(float), pa_outbuf, 0); + } + err = pa_open_callback(rate, inchans, outchans, + framesperbuf, nbuffers, pa_indev, pa_outdev, pa_fifo_callback); +#else + err = pa_open_callback(rate, inchans, outchans, + framesperbuf, nbuffers, pa_indev, pa_outdev, 0); +#endif + } + pa_started = 0; + pa_nbuffers = nbuffers; + if ( err != paNoError ) + { + post("Error opening audio: %s", Pa_GetErrorText(err)); + /* Pa_Terminate(); */ + return (1); + } + else if (sys_verbose) + post("... opened OK."); + return (0); +} + +void pa_close_audio( void) +{ + if (pa_stream) + { + Pa_AbortStream(pa_stream); + Pa_CloseStream(pa_stream); + } + pa_stream = 0; +#ifdef FAKEBLOCKING + if (pa_inbuf) + free((char *)pa_inbuf), pa_inbuf = 0; + if (pa_outbuf) + free((char *)pa_outbuf), pa_outbuf = 0; +#endif +} + +int pa_send_dacs(void) +{ + t_sample *fp; + float *fp2, *fp3; + float *conversionbuf; + int j, k; + int rtnval = SENDDACS_YES; +#ifndef FAKEBLOCKING + double timebefore; +#endif /* FAKEBLOCKING */ + if ((!STUFF->st_inchannels && !STUFF->st_outchannels) || !pa_stream) + return (SENDDACS_NO); + conversionbuf = (float *)alloca((STUFF->st_inchannels > STUFF->st_outchannels? + STUFF->st_inchannels:STUFF->st_outchannels) * DEFDACBLKSIZE * sizeof(float)); + +#ifdef FAKEBLOCKING + if (!STUFF->st_inchannels) /* if no input channels sync on output */ + { +#ifdef THREADSIGNAL + pthread_mutex_lock(&pa_mutex); +#endif + while (sys_ringbuf_getwriteavailable(&pa_outring) < + (long)(STUFF->st_outchannels * DEFDACBLKSIZE * sizeof(float))) + { + rtnval = SENDDACS_SLEPT; +#ifdef THREADSIGNAL + pthread_cond_wait(&pa_sem, &pa_mutex); +#else +#ifdef _WIN32 + Sleep(1); +#else + usleep(1000); +#endif /* _WIN32 */ +#endif /* THREADSIGNAL */ + } +#ifdef THREADSIGNAL + pthread_mutex_unlock(&pa_mutex); +#endif + } + /* write output */ + if (STUFF->st_outchannels) + { + for (j = 0, fp = STUFF->st_soundout, fp2 = conversionbuf; + j < STUFF->st_outchannels; j++, fp2++) + for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE; + k++, fp++, fp3 += STUFF->st_outchannels) + *fp3 = *fp; + sys_ringbuf_write(&pa_outring, conversionbuf, + STUFF->st_outchannels*(DEFDACBLKSIZE*sizeof(float)), pa_outbuf); + } + if (STUFF->st_inchannels) /* if there is input sync on it */ + { +#ifdef THREADSIGNAL + pthread_mutex_lock(&pa_mutex); +#endif + while (sys_ringbuf_getreadavailable(&pa_inring) < + (long)(STUFF->st_inchannels * DEFDACBLKSIZE * sizeof(float))) + { + rtnval = SENDDACS_SLEPT; +#ifdef THREADSIGNAL + pthread_cond_wait(&pa_sem, &pa_mutex); +#else +#ifdef _WIN32 + Sleep(1); +#else + usleep(1000); +#endif /* _WIN32 */ +#endif /* THREADSIGNAL */ + } +#ifdef THREADSIGNAL + pthread_mutex_unlock(&pa_mutex); +#endif + } + if (STUFF->st_inchannels) + { + sys_ringbuf_read(&pa_inring, conversionbuf, + STUFF->st_inchannels*(DEFDACBLKSIZE*sizeof(float)), pa_inbuf); + for (j = 0, fp = STUFF->st_soundin, fp2 = conversionbuf; + j < STUFF->st_inchannels; j++, fp2++) + for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE; + k++, fp++, fp3 += STUFF->st_inchannels) + *fp = *fp3; + } + +#else /* FAKEBLOCKING */ + timebefore = sys_getrealtime(); + /* write output */ + if (STUFF->st_outchannels) + { + if (!pa_started) + { + memset(conversionbuf, 0, + STUFF->st_outchannels * DEFDACBLKSIZE * sizeof(float)); + for (j = 0; j < pa_nbuffers-1; j++) + Pa_WriteStream(pa_stream, conversionbuf, DEFDACBLKSIZE); + } + for (j = 0, fp = STUFF->st_soundout, fp2 = conversionbuf; + j < STUFF->st_outchannels; j++, fp2++) + for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE; + k++, fp++, fp3 += STUFF->st_outchannels) + *fp3 = *fp; + Pa_WriteStream(pa_stream, conversionbuf, DEFDACBLKSIZE); + } + + if (STUFF->st_inchannels) + { + Pa_ReadStream(pa_stream, conversionbuf, DEFDACBLKSIZE); + for (j = 0, fp = STUFF->st_soundin, fp2 = conversionbuf; + j < STUFF->st_inchannels; j++, fp2++) + for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE; + k++, fp++, fp3 += STUFF->st_inchannels) + *fp = *fp3; + } + if (sys_getrealtime() - timebefore > 0.002) + { + rtnval = SENDDACS_SLEPT; + } +#endif /* FAKEBLOCKING */ + pa_started = 1; + + memset(STUFF->st_soundout, 0, + DEFDACBLKSIZE*sizeof(t_sample)*STUFF->st_outchannels); + return (rtnval); +} + + /* scanning for devices */ +void pa_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize) +{ + int i, nin = 0, nout = 0, ndev; + *canmulti = 1; /* one dev each for input and output */ + + pa_init(); + ndev = Pa_GetDeviceCount(); + for (i = 0; i < ndev; i++) + { + const PaDeviceInfo *pdi = Pa_GetDeviceInfo(i); + if (pdi->maxInputChannels > 0 && nin < maxndev) + { + /* LATER figure out how to get API name correctly */ + snprintf(indevlist + nin * devdescsize, devdescsize, +#ifdef _WIN32 + "%s:%s", (pdi->hostApi == 0 ? "MMIO" : (pdi->hostApi == 1 ? "ASIO" : "?")), +#else +#ifdef __APPLE__ + "%s", +#else + "(%d) %s", pdi->hostApi, +#endif +#endif + pdi->name); + nin++; + } + if (pdi->maxOutputChannels > 0 && nout < maxndev) + { + snprintf(outdevlist + nout * devdescsize, devdescsize, +#ifdef _WIN32 + "%s:%s", (pdi->hostApi == 0 ? "MMIO" : (pdi->hostApi == 1 ? "ASIO" : "?")), +#else +#ifdef __APPLE__ + "%s", +#else + "(%d) %s", pdi->hostApi, +#endif +#endif + pdi->name); + nout++; + } + } + *nindevs = nin; + *noutdevs = nout; +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_audio_paring.c b/ports/camomile/source/LibPd/pure-data/src/s_audio_paring.c new file mode 100644 index 00000000..fa80f2ea --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_audio_paring.c @@ -0,0 +1,255 @@ +/* + * ringbuffer.c + * Ring Buffer utility.. + * + * Author: Phil Burk, http://www.softsynth.com + * + * This program uses the PortAudio Portable Audio Library. + * For more information see: http://www.audiomulch.com/portaudio/ + * Copyright (c) 1999-2000 Ross Bencina and Phil Burk + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * modified 2002/07/13 by olaf.matthes@gmx.de to allow any number if channels + * + * extensively hacked by msp@ucsd.edu for various reasons + * + */ + +#include +#include +#include +#include "s_audio_paring.h" +#include + +/* Clear buffer. Should only be called when buffer is NOT being read. */ +static void sys_ringbuf_Flush(PA_VOLATILE sys_ringbuf *rbuf, + PA_VOLATILE void *dataPtr, long nfill); + +/* Get address of region(s) to which we can write data. +** If the region is contiguous, size2 will be zero. +** If non-contiguous, size2 will be the size of second region. +** Returns room available to be written or numBytes, whichever is smaller. +*/ +static long sys_ringbuf_GetWriteRegions(PA_VOLATILE sys_ringbuf *rbuf, + long numBytes, PA_VOLATILE void **dataPtr1, long *sizePtr1, + PA_VOLATILE void **dataPtr2, long *sizePtr2, PA_VOLATILE char *buffer); +static long sys_ringbuf_AdvanceWriteIndex(PA_VOLATILE sys_ringbuf *rbuf, + long numBytes); + +/* Get address of region(s) from which we can read data. +** If the region is contiguous, size2 will be zero. +** If non-contiguous, size2 will be the size of second region. +** Returns room available to be read or numBytes, whichever is smaller. +*/ +static long sys_ringbuf_GetReadRegions(PA_VOLATILE sys_ringbuf *rbuf, + long numBytes, PA_VOLATILE void **dataPtr1, long *sizePtr1, + PA_VOLATILE void **dataPtr2, long *sizePtr2, PA_VOLATILE char *buffer); + +static long sys_ringbuf_AdvanceReadIndex(PA_VOLATILE sys_ringbuf *rbuf, + long numBytes ); + +/*************************************************************************** + * Initialize FIFO. + */ +long sys_ringbuf_init(PA_VOLATILE sys_ringbuf *rbuf, long numBytes, + PA_VOLATILE char *dataPtr, long nfill) +{ + rbuf->bufferSize = numBytes; + sys_ringbuf_Flush(rbuf, dataPtr, nfill); + return 0; +} +/*************************************************************************** +** Return number of bytes available for reading. */ +long sys_ringbuf_getreadavailable(PA_VOLATILE sys_ringbuf *rbuf) +{ + long ret = rbuf->writeIndex - rbuf->readIndex; + if (ret < 0) + ret += 2 * rbuf->bufferSize; + if (ret < 0 || ret > rbuf->bufferSize) + fprintf(stderr, + "consistency check failed: sys_ringbuf_getreadavailable\n"); + return ( ret ); +} +/*************************************************************************** +** Return number of bytes available for writing. */ +long sys_ringbuf_getwriteavailable(PA_VOLATILE sys_ringbuf *rbuf) +{ + return ( rbuf->bufferSize - sys_ringbuf_getreadavailable(rbuf)); +} + +/*************************************************************************** +** Clear buffer. Should only be called when buffer is NOT being read. */ +static void sys_ringbuf_Flush(PA_VOLATILE sys_ringbuf *rbuf, + PA_VOLATILE void *dataPtr, long nfill) +{ + PA_VOLATILE char *s; + long n; + rbuf->readIndex = 0; + rbuf->writeIndex = nfill; + for (n = nfill, s = dataPtr; n--; s++) + *s = 0; +} + +/*************************************************************************** +** Get address of region(s) to which we can write data. +** If the region is contiguous, size2 will be zero. +** If non-contiguous, size2 will be the size of second region. +** Returns room available to be written or numBytes, whichever is smaller. +*/ +static long sys_ringbuf_GetWriteRegions(PA_VOLATILE sys_ringbuf *rbuf, + long numBytes, PA_VOLATILE void **dataPtr1, long *sizePtr1, + PA_VOLATILE void **dataPtr2, long *sizePtr2, PA_VOLATILE char *buffer) +{ + long index; + long available = sys_ringbuf_getwriteavailable( rbuf ); + if( numBytes > available ) numBytes = available; + /* Check to see if write is not contiguous. */ + index = rbuf->writeIndex; + while (index >= rbuf->bufferSize) + index -= rbuf->bufferSize; + if( (index + numBytes) > rbuf->bufferSize ) + { + /* Write data in two blocks that wrap the buffer. */ + long firstHalf = rbuf->bufferSize - index; + *dataPtr1 = &buffer[index]; + *sizePtr1 = firstHalf; + *dataPtr2 = &buffer[0]; + *sizePtr2 = numBytes - firstHalf; + } + else + { + *dataPtr1 = &buffer[index]; + *sizePtr1 = numBytes; + *dataPtr2 = NULL; + *sizePtr2 = 0; + } + return numBytes; +} + + +/*************************************************************************** +*/ +static long sys_ringbuf_AdvanceWriteIndex(PA_VOLATILE sys_ringbuf *rbuf, + long numBytes) +{ + long ret = (rbuf->writeIndex + numBytes); + if ( ret >= 2 * rbuf->bufferSize) + ret -= 2 * rbuf->bufferSize; /* check for end of buffer */ + return rbuf->writeIndex = ret; +} + +/*************************************************************************** +** Get address of region(s) from which we can read data. +** If the region is contiguous, size2 will be zero. +** If non-contiguous, size2 will be the size of second region. +** Returns room available to be written or numBytes, whichever is smaller. +*/ +static long sys_ringbuf_GetReadRegions(PA_VOLATILE sys_ringbuf *rbuf, + long numBytes, PA_VOLATILE void **dataPtr1, long *sizePtr1, + PA_VOLATILE void **dataPtr2, long *sizePtr2, PA_VOLATILE char *buffer) +{ + long index; + long available = sys_ringbuf_getreadavailable( rbuf ); + if( numBytes > available ) numBytes = available; + /* Check to see if read is not contiguous. */ + index = rbuf->readIndex; + while (index >= rbuf->bufferSize) + index -= rbuf->bufferSize; + + if( (index + numBytes) > rbuf->bufferSize ) + { + /* Write data in two blocks that wrap the buffer. */ + long firstHalf = rbuf->bufferSize - index; + *dataPtr1 = &buffer[index]; + *sizePtr1 = firstHalf; + *dataPtr2 = &buffer[0]; + *sizePtr2 = numBytes - firstHalf; + } + else + { + *dataPtr1 = &buffer[index]; + *sizePtr1 = numBytes; + *dataPtr2 = NULL; + *sizePtr2 = 0; + } + return numBytes; +} +/*************************************************************************** +*/ +static long sys_ringbuf_AdvanceReadIndex(PA_VOLATILE sys_ringbuf *rbuf, + long numBytes) +{ + long ret = (rbuf->readIndex + numBytes); + if( ret >= 2 * rbuf->bufferSize) + ret -= 2 * rbuf->bufferSize; + return rbuf->readIndex = ret; +} + +/*************************************************************************** +** Return bytes written. */ +long sys_ringbuf_write(PA_VOLATILE sys_ringbuf *rbuf, const void *data, + long numBytes, PA_VOLATILE char *buffer) +{ + long size1, size2, numWritten; + PA_VOLATILE void *data1, *data2; + numWritten = sys_ringbuf_GetWriteRegions( rbuf, numBytes, &data1, &size1, + &data2, &size2, buffer); + if( size2 > 0 ) + { + + memcpy((void *)data1, data, size1 ); + data = ((char *)data) + size1; + memcpy((void *)data2, data, size2 ); + } + else + { + memcpy((void *)data1, data, size1 ); + } + sys_ringbuf_AdvanceWriteIndex( rbuf, numWritten ); + return numWritten; +} + +/*************************************************************************** +** Return bytes read. */ +long sys_ringbuf_read(PA_VOLATILE sys_ringbuf *rbuf, void *data, long numBytes, + PA_VOLATILE char *buffer) +{ + long size1, size2, numRead; + PA_VOLATILE void *data1, *data2; + numRead = sys_ringbuf_GetReadRegions( rbuf, numBytes, &data1, &size1, + &data2, &size2, buffer); + if( size2 > 0 ) + { + memcpy(data, (void *)data1, size1 ); + data = ((char *)data) + size1; + memcpy(data, (void *)data2, size2 ); + } + else + { + memcpy( data, (void *)data1, size1 ); + } + sys_ringbuf_AdvanceReadIndex( rbuf, numRead ); + return numRead; +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_audio_paring.h b/ports/camomile/source/LibPd/pure-data/src/s_audio_paring.h new file mode 100644 index 00000000..40adeae7 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_audio_paring.h @@ -0,0 +1,75 @@ +#ifndef _RINGBUFFER_H +#define _RINGBUFFER_H +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ringbuffer.h + * Ring Buffer utility.. + * + * Author: Phil Burk, http://www.softsynth.com + * + * This program is distributed with the PortAudio Portable Audio Library. + * For more information see: http://www.audiomulch.com/portaudio/ + * Copyright (c) 1999-2000 Ross Bencina and Phil Burk + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/* If it's ever desired to use shared memory so that one process reads and +another one writes to the same ring buffer, define this as 'volatile' : */ +#define PA_VOLATILE + +typedef struct +{ + long bufferSize; /* Number of bytes in FIFO. + Set by sys_ringbuf_init */ + PA_VOLATILE long writeIndex; /* Index of next writable byte. + Set by sys_ringbuf_AdvanceWriteIndex */ + PA_VOLATILE long readIndex; /* Index of next readable byte. + Set by sys_ringbuf_AdvanceReadIndex */ +} sys_ringbuf; + +/* Initialize Ring Buffer. */ +long sys_ringbuf_init(PA_VOLATILE sys_ringbuf *rbuf, long numBytes, + PA_VOLATILE char *dataPtr, long nfill); + +/* Return number of bytes available for writing. */ +long sys_ringbuf_getwriteavailable(PA_VOLATILE sys_ringbuf *rbuf); +/* Return number of bytes available for read. */ +long sys_ringbuf_getreadavailable(PA_VOLATILE sys_ringbuf *rbuf); +/* Return bytes written. */ +long sys_ringbuf_write(PA_VOLATILE sys_ringbuf *rbuf, const void *data, + long numBytes, PA_VOLATILE char *buffer); +/* Return bytes read. */ +long sys_ringbuf_read(PA_VOLATILE sys_ringbuf *rbuf, void *data, long numBytes, + PA_VOLATILE char *buffer); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _RINGBUFFER_H */ diff --git a/ports/camomile/source/LibPd/pure-data/src/s_entry.c b/ports/camomile/source/LibPd/pure-data/src/s_entry.c new file mode 100644 index 00000000..006b33f9 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_entry.c @@ -0,0 +1,36 @@ +/* In MSW, this is all there is to pd; the rest sits in a "pdlib" dll so +that externs can link back to functions defined in pd. */ + +int sys_main(int argc, char **argv); + +/* + * gcc does not support the __try stuff, only MSVC. Also, MinGW allows you to + * use main() instead of WinMain(). + */ +#if defined(_MSC_VER) && !defined(COMMANDVERSION) +#include +#include + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + __try { + sys_main(__argc,__argv); + } + __finally + { + printf("caught an exception; stopping\n"); + } + return (0); +} + +#else /* not _MSC_VER ... */ +int main(int argc, char **argv) +{ + return (sys_main(argc, argv)); +} +#endif /* _MSC_VER */ + + diff --git a/ports/camomile/source/LibPd/pure-data/src/s_file.c b/ports/camomile/source/LibPd/pure-data/src/s_file.c new file mode 100644 index 00000000..cf8752e8 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_file.c @@ -0,0 +1,697 @@ +/* Copyright (c) 1997-2004 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* + * this file implements a mechanism for storing and retrieving preferences. + * Should later be renamed "preferences.c" or something. + * + * In unix this is handled by the "~/.pdsettings" file, in windows by + * the registry, and in MacOS by the Preferences system. + */ + +#include "m_pd.h" +#include "s_stuff.h" +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#include +#include +#include +#include +#include +#endif +#ifdef _WIN32 +#include +#include +#include +#endif +#ifdef _MSC_VER /* This is only for Microsoft's compiler, not cygwin, e.g. */ +#define snprintf _snprintf +#endif + +void sys_doflags( void); + +static PERTHREAD char *sys_prefbuf; +static PERTHREAD int sys_prefbufsize; +static PERTHREAD FILE *sys_prefsavefp; + +static void sys_initloadpreferences_file(const char *filename) +{ + int fd; + long length; + if ((fd = open(filename, 0)) < 0) + { + if (sys_verbose) + perror(filename); + return; + } + length = lseek(fd, 0, 2); + if (length < 0) + { + if (sys_verbose) + perror(filename); + close(fd); + return; + } + lseek(fd, 0, 0); + if (!(sys_prefbuf = malloc(length + 2))) + { + error("couldn't allocate memory for preferences buffer"); + close(fd); + return; + } + sys_prefbuf[0] = '\n'; + if (read(fd, sys_prefbuf+1, length) < length) + { + perror(filename); + sys_prefbuf[0] = 0; + close(fd); + return; + } + sys_prefbuf[length+1] = 0; + close(fd); + if (sys_verbose) + post("success reading preferences from: %s", filename); +} + +static int sys_getpreference_file(const char *key, char *value, int size) +{ + char searchfor[80], *where, *whereend; + if (!sys_prefbuf) + return (0); + sprintf(searchfor, "\n%s:", key); + where = strstr(sys_prefbuf, searchfor); + if (!where) + return (0); + where += strlen(searchfor); + while (*where == ' ' || *where == '\t') + where++; + for (whereend = where; *whereend && *whereend != '\n'; whereend++) + ; + if (*whereend == '\n') + whereend--; + if (whereend > where + size - 1) + whereend = where + size - 1; + strncpy(value, where, whereend+1-where); + value[whereend+1-where] = 0; + return (1); +} + +static void sys_doneloadpreferences_file( void) +{ + if (sys_prefbuf) + free(sys_prefbuf); +} + +static void sys_initsavepreferences_file(const char *filename) +{ + if ((sys_prefsavefp = fopen(filename, "w")) == NULL) + pd_error(0, "%s: %s", filename, strerror(errno)); +} + +static void sys_putpreference_file(const char *key, const char *value) +{ + if (sys_prefsavefp) + fprintf(sys_prefsavefp, "%s: %s\n", + key, value); +} + +static void sys_donesavepreferences_file( void) +{ + if (sys_prefsavefp) + { + fclose(sys_prefsavefp); + sys_prefsavefp = 0; + } +} + + +/***** linux/android/BSD etc: read and write to ~/.pdsettings file ******/ +#if !defined(_WIN32) && !defined(__APPLE__) + +static void sys_initloadpreferences( void) +{ + char filenamebuf[MAXPDSTRING], *homedir = getenv("HOME"); + int fd, length; + char user_prefs_file[MAXPDSTRING]; /* user prefs file */ + /* default prefs embedded in the package */ + char default_prefs_file[MAXPDSTRING]; + struct stat statbuf; + + snprintf(default_prefs_file, MAXPDSTRING, "%s/default.pdsettings", + sys_libdir->s_name); + snprintf(user_prefs_file, MAXPDSTRING, "%s/.pdsettings", + (homedir ? homedir : ".")); + if (stat(user_prefs_file, &statbuf) == 0) + strncpy(filenamebuf, user_prefs_file, MAXPDSTRING); + else if (stat(default_prefs_file, &statbuf) == 0) + strncpy(filenamebuf, default_prefs_file, MAXPDSTRING); + else return; + filenamebuf[MAXPDSTRING-1] = 0; + sys_initloadpreferences_file(filenamebuf); +} + +static int sys_getpreference(const char *key, char *value, int size) +{ + return (sys_getpreference_file(key, value, size)); +} + +static void sys_doneloadpreferences( void) +{ + sys_doneloadpreferences_file(); +} + +static void sys_initsavepreferences( void) +{ + char filenamebuf[MAXPDSTRING], + *homedir = getenv("HOME"); + FILE *fp; + + if (!homedir) + return; + snprintf(filenamebuf, MAXPDSTRING, "%s/.pdsettings", homedir); + filenamebuf[MAXPDSTRING-1] = 0; + sys_initsavepreferences_file(filenamebuf); +} + +static void sys_putpreference(const char *key, const char *value) +{ + sys_putpreference_file(key, value); +} + +static void sys_donesavepreferences( void) +{ + sys_donesavepreferences_file(); +} + +#else /* !defined(_WIN32) && !defined(__APPLE__) */ + +static void sys_initloadpreferences( void) +{ + if (sys_prefbuf) + bug("sys_initloadpreferences"); +} +static void sys_doneloadpreferences( void) +{ + if (sys_prefbuf) + sys_doneloadpreferences_file(); +} +static void sys_initsavepreferences( void) +{ + if (sys_prefsavefp) + bug("sys_initsavepreferences"); +} +static void sys_donesavepreferences( void) +{ + if (sys_prefsavefp) + sys_donesavepreferences_file(); +} + +static int sys_getpreference(const char *key, char *value, int size) +{ + if (sys_prefbuf) + return (sys_getpreference_file(key, value, size)); + else + { +#ifdef _WIN32 + HKEY hkey; + DWORD bigsize = size; + LONG err = RegOpenKeyEx(HKEY_CURRENT_USER, + "Software\\Pure-Data", 0, KEY_QUERY_VALUE, &hkey); + if (err != ERROR_SUCCESS) + return (0); + err = RegQueryValueEx(hkey, key, 0, 0, value, &bigsize); + if (err != ERROR_SUCCESS) + { + RegCloseKey(hkey); + return (0); + } + RegCloseKey(hkey); + return (1); +#endif /* _WIN32 */ +#ifdef __APPLE__ + char cmdbuf[256]; + int nread = 0, nleft = size; + char embedded_prefs[MAXPDSTRING]; + char user_prefs[MAXPDSTRING]; + char *homedir = getenv("HOME"); + struct stat statbuf; + /* the 'defaults' command expects the filename without .plist at the + end */ + snprintf(embedded_prefs, MAXPDSTRING, "%s/../org.puredata.pd", + sys_libdir->s_name); + snprintf(user_prefs, MAXPDSTRING, + "%s/Library/Preferences/org.puredata.pd.plist", homedir); + if (stat(user_prefs, &statbuf) == 0) + snprintf(cmdbuf, 256, "defaults read org.puredata.pd %s 2> /dev/null\n", + key); + else snprintf(cmdbuf, 256, "defaults read %s %s 2> /dev/null\n", + embedded_prefs, key); + FILE *fp = popen(cmdbuf, "r"); + while (nread < size) + { + int newread = fread(value+nread, 1, size-nread, fp); + if (newread <= 0) + break; + nread += newread; + } + pclose(fp); + if (nread < 1) + return (0); + if (nread >= size) + nread = size-1; + value[nread] = 0; + if (value[nread-1] == '\n') /* remove newline character at end */ + value[nread-1] = 0; + return(1); +#endif /* __APPLE__ */ + } +} + +static void sys_putpreference(const char *key, const char *value) +{ + if (sys_prefsavefp) + sys_putpreference_file(key, value); + else + { +#ifdef _WIN32 + HKEY hkey; + LONG err = RegCreateKeyEx(HKEY_CURRENT_USER, + "Software\\Pure-Data", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, + NULL, &hkey, NULL); + if (err != ERROR_SUCCESS) + { + error("unable to create registry entry: %s\n", key); + return; + } + err = RegSetValueEx(hkey, key, 0, REG_EXPAND_SZ, value, strlen(value)+1); + if (err != ERROR_SUCCESS) + error("unable to set registry entry: %s\n", key); + RegCloseKey(hkey); +#endif /* _WIN32 */ +#ifdef __APPLE__ + char cmdbuf[MAXPDSTRING]; + snprintf(cmdbuf, MAXPDSTRING, + "defaults write org.puredata.pd %s \"%s\" 2> /dev/null\n", key, value); + system(cmdbuf); +#endif /* __APPLE__ */ + } +} +#endif /* !defined(_WIN32) && !defined(__APPLE__) */ + +void sys_loadpreferences(const char *filename, int startingup) +{ + int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV]; + int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV]; + int nmidiindev, midiindev[MAXMIDIINDEV]; + int nmidioutdev, midioutdev[MAXMIDIOUTDEV]; + int i, rate = 0, advance = -1, callback = 0, blocksize = 0, + api, midiapi, nolib, maxi; + char prefbuf[MAXPDSTRING], keybuf[80]; + + if (*filename) + sys_initloadpreferences_file(filename); + else sys_initloadpreferences(); + /* load audio preferences */ + if (sys_getpreference("audioapi", prefbuf, MAXPDSTRING) + && sscanf(prefbuf, "%d", &api) > 0) + sys_set_audio_api(api); + /* JMZ/MB: brackets for initializing */ + if (sys_getpreference("noaudioin", prefbuf, MAXPDSTRING) && + (!strcmp(prefbuf, ".") || !strcmp(prefbuf, "True"))) + naudioindev = 0; + else + { + for (i = 0, naudioindev = 0; i < MAXAUDIOINDEV; i++) + { + /* first try to find a name - if that matches an existing + device use it. Otherwise fall back to device number. */ + int devn; + /* read in device number and channel count */ + sprintf(keybuf, "audioindev%d", i+1); + if (!sys_getpreference(keybuf, prefbuf, MAXPDSTRING)) + break; + if (sscanf(prefbuf, "%d %d", &audioindev[i], &chindev[i]) < 2) + break; + /* possibly override device number if the device name was + also saved and if it matches one we have now */ + sprintf(keybuf, "audioindevname%d", i+1); + if (sys_getpreference(keybuf, prefbuf, MAXPDSTRING) + && (devn = sys_audiodevnametonumber(0, prefbuf)) >= 0) + audioindev[i] = devn; + naudioindev++; + } + /* if no preferences at all, set -1 for default behavior */ + if (naudioindev == 0) + naudioindev = -1; + } + /* JMZ/MB: brackets for initializing */ + if (sys_getpreference("noaudioout", prefbuf, MAXPDSTRING) && + (!strcmp(prefbuf, ".") || !strcmp(prefbuf, "True"))) + naudiooutdev = 0; + else + { + for (i = 0, naudiooutdev = 0; i < MAXAUDIOOUTDEV; i++) + { + int devn; + sprintf(keybuf, "audiooutdev%d", i+1); + if (!sys_getpreference(keybuf, prefbuf, MAXPDSTRING)) + break; + if (sscanf(prefbuf, "%d %d", &audiooutdev[i], &choutdev[i]) < 2) + break; + sprintf(keybuf, "audiooutdevname%d", i+1); + if (sys_getpreference(keybuf, prefbuf, MAXPDSTRING) + && (devn = sys_audiodevnametonumber(1, prefbuf)) >= 0) + audiooutdev[i] = devn; + naudiooutdev++; + } + if (naudiooutdev == 0) + naudiooutdev = -1; + } + if (sys_getpreference("rate", prefbuf, MAXPDSTRING)) + sscanf(prefbuf, "%d", &rate); + if (sys_getpreference("audiobuf", prefbuf, MAXPDSTRING)) + sscanf(prefbuf, "%d", &advance); + if (sys_getpreference("callback", prefbuf, MAXPDSTRING)) + sscanf(prefbuf, "%d", &callback); + if (sys_getpreference("blocksize", prefbuf, MAXPDSTRING)) + sscanf(prefbuf, "%d", &blocksize); + sys_set_audio_settings(naudioindev, audioindev, naudioindev, chindev, + naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance, + callback, blocksize); + + /* load MIDI preferences */ + if (sys_getpreference("midiapi", prefbuf, MAXPDSTRING) + && sscanf(prefbuf, "%d", &midiapi) > 0) + sys_set_midi_api(midiapi); + /* JMZ/MB: brackets for initializing */ + if (sys_getpreference("nomidiin", prefbuf, MAXPDSTRING) && + (!strcmp(prefbuf, ".") || !strcmp(prefbuf, "True"))) + nmidiindev = 0; + else for (i = 0, nmidiindev = 0; i < MAXMIDIINDEV; i++) + { + /* first try to find a name - if that matches an existing device + use it. Otherwise fall back to device number. */ + int devn; + sprintf(keybuf, "midiindevname%d", i+1); + if (sys_getpreference(keybuf, prefbuf, MAXPDSTRING) + && (devn = sys_mididevnametonumber(0, prefbuf)) >= 0) + midiindev[i] = devn; + else + { + sprintf(keybuf, "midiindev%d", i+1); + if (!sys_getpreference(keybuf, prefbuf, MAXPDSTRING)) + break; + if (sscanf(prefbuf, "%d", &midiindev[i]) < 1) + break; + } + nmidiindev++; + } + /* JMZ/MB: brackets for initializing */ + if (sys_getpreference("nomidiout", prefbuf, MAXPDSTRING) && + (!strcmp(prefbuf, ".") || !strcmp(prefbuf, "True"))) + nmidioutdev = 0; + else for (i = 0, nmidioutdev = 0; i < MAXMIDIOUTDEV; i++) + { + int devn; + sprintf(keybuf, "midioutdevname%d", i+1); + if (sys_getpreference(keybuf, prefbuf, MAXPDSTRING) + && (devn = sys_mididevnametonumber(1, prefbuf)) >= 0) + midioutdev[i] = devn; + else + { + sprintf(keybuf, "midioutdev%d", i+1); + if (!sys_getpreference(keybuf, prefbuf, MAXPDSTRING)) + break; + if (sscanf(prefbuf, "%d", &midioutdev[i]) < 1) + break; + } + nmidioutdev++; + } + sys_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev, 0); + + /* search path */ + if (sys_getpreference("npath", prefbuf, MAXPDSTRING)) + sscanf(prefbuf, "%d", &maxi); + else maxi = 0x7fffffff; + for (i = 0; ist_searchpath = + namelist_append_files(STUFF->st_searchpath, prefbuf); + } + if (sys_getpreference("standardpath", prefbuf, MAXPDSTRING)) + sscanf(prefbuf, "%d", &sys_usestdpath); + if (sys_getpreference("verbose", prefbuf, MAXPDSTRING)) + sscanf(prefbuf, "%d", &sys_verbose); + + /* startup settings */ + if (sys_getpreference("nloadlib", prefbuf, MAXPDSTRING)) + sscanf(prefbuf, "%d", &maxi); + else maxi = 0x7fffffff; + for (i = 0; ist_externlist = namelist_append_files(STUFF->st_externlist, prefbuf); + } + if (sys_getpreference("defeatrt", prefbuf, MAXPDSTRING)) + sscanf(prefbuf, "%d", &sys_defeatrt); + if (sys_getpreference("flags", prefbuf, MAXPDSTRING) && + strcmp(prefbuf, ".")) + { + sys_flags = gensym(prefbuf); + if (startingup) + sys_doflags(); + } + if (sys_defeatrt) + sys_hipriority = 0; + else +#if defined(__linux__) || defined(__CYGWIN__) + sys_hipriority = 1; +#else +#if defined(_WIN32) || defined(ANDROID) + sys_hipriority = 0; +#else + sys_hipriority = 1; +#endif +#endif + if (sys_getpreference("zoom", prefbuf, MAXPDSTRING)) + sscanf(prefbuf, "%d", &sys_zoom_open); + + sys_doneloadpreferences(); +} + +void sys_savepreferences(const char *filename) +{ + int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV]; + int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV]; + int i, rate, advance, callback, blocksize; + char buf1[MAXPDSTRING], buf2[MAXPDSTRING]; + int nmidiindev, midiindev[MAXMIDIINDEV]; + int nmidioutdev, midioutdev[MAXMIDIOUTDEV]; + + if (filename && *filename) + sys_initsavepreferences_file(filename); + else sys_initsavepreferences(); + /* audio settings */ + sprintf(buf1, "%d", sys_audioapi); + sys_putpreference("audioapi", buf1); + + sys_get_audio_params(&naudioindev, audioindev, chindev, + &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback, + &blocksize); + + sys_putpreference("noaudioin", (naudioindev <= 0 ? "True" : "False")); + for (i = 0; i < naudioindev; i++) + { + sprintf(buf1, "audioindev%d", i+1); + sprintf(buf2, "%d %d", audioindev[i], chindev[i]); + sys_putpreference(buf1, buf2); + sprintf(buf1, "audioindevname%d", i+1); + sys_audiodevnumbertoname(0, audioindev[i], buf2, MAXPDSTRING); + if (! *buf2) + strcat(buf2, "?"); + sys_putpreference(buf1, buf2); + } + sys_putpreference("noaudioout", (naudiooutdev <= 0 ? "True" : "False")); + for (i = 0; i < naudiooutdev; i++) + { + sprintf(buf1, "audiooutdev%d", i+1); + sprintf(buf2, "%d %d", audiooutdev[i], choutdev[i]); + sys_putpreference(buf1, buf2); + sprintf(buf1, "audiooutdevname%d", i+1); + sys_audiodevnumbertoname(1, audiooutdev[i], buf2, MAXPDSTRING); + if (! *buf2) + strcat(buf2, "?"); + sys_putpreference(buf1, buf2); + } + + sprintf(buf1, "%d", advance); + sys_putpreference("audiobuf", buf1); + + sprintf(buf1, "%d", rate); + sys_putpreference("rate", buf1); + + sprintf(buf1, "%d", callback); + sys_putpreference("callback", buf1); + + sprintf(buf1, "%d", blocksize); + sys_putpreference("blocksize", buf1); + + /* MIDI settings */ + sprintf(buf1, "%d", sys_midiapi); + sys_putpreference("midiapi", buf1); + + sys_get_midi_params(&nmidiindev, midiindev, &nmidioutdev, midioutdev); + sys_putpreference("nomidiin", (nmidiindev <= 0 ? "True" : "False")); + for (i = 0; i < nmidiindev; i++) + { + sprintf(buf1, "midiindev%d", i+1); + sprintf(buf2, "%d", midiindev[i]); + sys_putpreference(buf1, buf2); + sprintf(buf1, "midiindevname%d", i+1); + sys_mididevnumbertoname(0, midiindev[i], buf2, MAXPDSTRING); + if (! *buf2) + strcat(buf2, "?"); + sys_putpreference(buf1, buf2); + } + sys_putpreference("nomidiout", (nmidioutdev <= 0 ? "True" : "False")); + for (i = 0; i < nmidioutdev; i++) + { + sprintf(buf1, "midioutdev%d", i+1); + sprintf(buf2, "%d", midioutdev[i]); + sys_putpreference(buf1, buf2); + sprintf(buf1, "midioutdevname%d", i+1); + sys_mididevnumbertoname(1, midioutdev[i], buf2, MAXPDSTRING); + if (! *buf2) + strcat(buf2, "?"); + sys_putpreference(buf1, buf2); + } + /* file search path */ + + for (i = 0; 1; i++) + { + char *pathelem = namelist_get(STUFF->st_searchpath, i); + if (!pathelem) + break; + sprintf(buf1, "path%d", i+1); + sys_putpreference(buf1, pathelem); + } + sprintf(buf1, "%d", i); + sys_putpreference("npath", buf1); + sprintf(buf1, "%d", sys_usestdpath); + sys_putpreference("standardpath", buf1); + sprintf(buf1, "%d", sys_verbose); + sys_putpreference("verbose", buf1); + + /* startup */ + for (i = 0; 1; i++) + { + char *pathelem = namelist_get(STUFF->st_externlist, i); + if (!pathelem) + break; + sprintf(buf1, "loadlib%d", i+1); + sys_putpreference(buf1, pathelem); + } + sprintf(buf1, "%d", i); + sys_putpreference("nloadlib", buf1); + sprintf(buf1, "%d", sys_defeatrt); + sys_putpreference("defeatrt", buf1); + sys_putpreference("flags", + (sys_flags ? sys_flags->s_name : "")); + /* misc */ + sprintf(buf1, "%d", sys_zoom_open); + sys_putpreference("zoom", buf1); + sys_putpreference("loading", "no"); + + sys_donesavepreferences(); +} + + /* calls from GUI to load/save from/to a file */ +void glob_loadpreferences(t_pd *dummy, t_symbol *filesym) +{ + sys_loadpreferences(filesym->s_name, 0); + sys_close_audio(); + sys_reopen_audio(); + sys_close_midi(); + sys_reopen_midi(); +} + +void glob_savepreferences(t_pd *dummy, t_symbol *filesym) +{ + sys_savepreferences(filesym->s_name); +} + +void glob_forgetpreferences(t_pd *dummy) +{ +#if !defined(_WIN32) && !defined(__APPLE__) + if (system("cat ~/.pdsettings >& /dev/null\n")) + post("no Pd settings to clear"); + else if (!system("rm ~/.pdsettings\n")) + post("removed .pdsettings file"); + else post("couldn't delete .pdsettings file"); +#endif /* !defined(_WIN32) && !defined(__APPLE__) */ +#ifdef __APPLE__ + char cmdbuf[MAXPDSTRING]; + int warn = 1; + if (!sys_getpreference("audioapi", cmdbuf, MAXPDSTRING)) + post("no Pd settings to clear"), warn = 0; + /* do it anyhow, why not... */ + snprintf(cmdbuf, MAXPDSTRING, + "defaults delete org.puredata.pd 2> /dev/null\n"); + if (system(cmdbuf) && warn) + post("failed to erase Pd settings"); + else if(warn) post("erased Pd settings"); +#endif /* __APPLE__ */ +#ifdef _WIN32 + HKEY hkey; + if (RegOpenKeyEx(HKEY_CURRENT_USER, + "Software", 0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) + post("no Pd settings to erase"); + else + { + if (RegDeleteKey(hkey, "Pure-Data") != ERROR_SUCCESS) + post("no Pd settings to erase"); + else post("erased Pd settings"); + RegCloseKey(hkey); + } +#endif /* _WIN32 */ +} + +int sys_oktoloadfiles(int done) +{ +#if defined(_WIN32) || defined(__APPLE__) + if (done) + { + sys_putpreference("loading", "no"); + return (1); + } + else + { + char prefbuf[MAXPDSTRING]; + if (sys_getpreference("loading", prefbuf, MAXPDSTRING) && + strcmp(prefbuf, "no")) + { + post( + "skipping loading preferences... Pd seems to have crashed on startup."); + post("(re-save preferences to reinstate them)"); + return (0); + } + else + { + sys_putpreference("loading", "yes"); + return (1); + } + } +#else + return (1); +#endif +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_inter.c b/ports/camomile/source/LibPd/pure-data/src/s_inter.c new file mode 100644 index 00000000..ffb3c46b --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_inter.c @@ -0,0 +1,1607 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* Pd side of the Pd/Pd-gui interface. Also, some system interface routines +that didn't really belong anywhere. */ + +#include "m_pd.h" +#include "s_stuff.h" +#include "m_imp.h" +#include "g_canvas.h" /* for GUI queueing stuff */ +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#ifdef HAVE_BSTRING_H +#include +#endif +#ifdef _WIN32 +#include +#include +#include +#include +#include +typedef int socklen_t; +#define EADDRINUSE WSAEADDRINUSE +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#include +#include +#else +#include +#endif + +#define stringify(s) str(s) +#define str(s) #s + +#define DEBUG_MESSUP 1 /* messages up from pd to pd-gui */ +#define DEBUG_MESSDOWN 2 /* messages down from pd-gui to pd */ + +#ifndef PDBINDIR +#define PDBINDIR "bin/" +#endif + +#ifndef PDGUIDIR +#define PDGUIDIR "tcl/" +#endif + +#ifndef WISH +# if defined _WIN32 +# define WISH "wish85.exe" +# elif defined __APPLE__ + // leave undefined to use dummy search path, otherwise + // this should be a full path to wish on mac +#else +# define WISH "wish" +# endif +#endif + +#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__) +#define LOCALHOST "127.0.0.1" +#else +#define LOCALHOST "localhost" +#endif + +#if PDTHREADS +#include "pthread.h" +#endif + +typedef struct _fdpoll +{ + int fdp_fd; + t_fdpollfn fdp_fn; + void *fdp_ptr; +} t_fdpoll; + +#define INBUFSIZE 4096 + +struct _socketreceiver +{ + char *sr_inbuf; + int sr_inhead; + int sr_intail; + void *sr_owner; + int sr_udp; + t_socketnotifier sr_notifier; + t_socketreceivefn sr_socketreceivefn; +}; + +typedef struct _guiqueue +{ + void *gq_client; + t_glist *gq_glist; + t_guicallbackfn gq_fn; + struct _guiqueue *gq_next; +} t_guiqueue; + +struct _instanceinter +{ + int i_havegui; + int i_nfdpoll; + t_fdpoll *i_fdpoll; + int i_maxfd; + int i_guisock; + t_socketreceiver *i_socketreceiver; + t_guiqueue *i_guiqueuehead; + t_binbuf *i_inbinbuf; + char *i_guibuf; + int i_guihead; + int i_guitail; + int i_guisize; + int i_waitingforping; + int i_bytessincelastping; + +#ifdef _WIN32 + LARGE_INTEGER i_inittime; + double i_freq; +#endif +#if PDTHREADS + pthread_mutex_t i_mutex; +#endif +}; + +extern int sys_guisetportnumber; +extern int sys_addhist(int phase); +void sys_set_searchpath(void); +void sys_set_extrapath(void); +void sys_set_startup(void); +void sys_stopgui( void); + +/* ----------- functions for timing, signals, priorities, etc --------- */ + +#ifdef _WIN32 + +static void sys_initntclock(void) +{ + LARGE_INTEGER f1; + LARGE_INTEGER now; + QueryPerformanceCounter(&now); + if (!QueryPerformanceFrequency(&f1)) + { + fprintf(stderr, "pd: QueryPerformanceFrequency failed\n"); + f1.QuadPart = 1; + } + pd_this->pd_inter->i_freq = f1.QuadPart; + pd_this->pd_inter->i_inittime = now; +} + +#if 0 + /* this is a version you can call if you did the QueryPerformanceCounter + call yourself. Necessary for time tagging incoming MIDI at interrupt + level, for instance; but we're not doing that just now. */ + +double nt_tixtotime(LARGE_INTEGER *dumbass) +{ + if (pd_this->pd_inter->i_freq == 0) sys_initntclock(); + return (((double)(dumbass->QuadPart - + pd_this->pd_inter->i_inittime.QuadPart)) / pd_this->pd_inter->i_freq); +} +#endif +#endif /* _WIN32 */ + + /* get "real time" in seconds; take the + first time we get called as a reference time of zero. */ +double sys_getrealtime(void) +{ +#ifndef _WIN32 + static struct timeval then; + struct timeval now; + gettimeofday(&now, 0); + if (then.tv_sec == 0 && then.tv_usec == 0) then = now; + return ((now.tv_sec - then.tv_sec) + + (1./1000000.) * (now.tv_usec - then.tv_usec)); +#else + LARGE_INTEGER now; + QueryPerformanceCounter(&now); + if (pd_this->pd_inter->i_freq == 0) sys_initntclock(); + return (((double)(now.QuadPart - + pd_this->pd_inter->i_inittime.QuadPart)) / pd_this->pd_inter->i_freq); +#endif +} + +extern int sys_nosleep; + +static int sys_domicrosleep(int microsec, int pollem) +{ + struct timeval timout; + int i, didsomething = 0; + t_fdpoll *fp; + timout.tv_sec = 0; + timout.tv_usec = (sys_nosleep ? 0 : microsec); + if (pollem) + { + fd_set readset, writeset, exceptset; + FD_ZERO(&writeset); + FD_ZERO(&readset); + FD_ZERO(&exceptset); + for (fp = pd_this->pd_inter->i_fdpoll, + i = pd_this->pd_inter->i_nfdpoll; i--; fp++) + FD_SET(fp->fdp_fd, &readset); +#ifdef _WIN32 + if (pd_this->pd_inter->i_maxfd == 0) + Sleep(microsec/1000); + else +#endif + if(select(pd_this->pd_inter->i_maxfd+1, + &readset, &writeset, &exceptset, &timout) < 0) + perror("microsleep select"); + for (i = 0; i < pd_this->pd_inter->i_nfdpoll; i++) + if (FD_ISSET(pd_this->pd_inter->i_fdpoll[i].fdp_fd, &readset)) + { +#ifdef THREAD_LOCKING + sys_lock(); +#endif + (*pd_this->pd_inter->i_fdpoll[i].fdp_fn) + (pd_this->pd_inter->i_fdpoll[i].fdp_ptr, + pd_this->pd_inter->i_fdpoll[i].fdp_fd); +#ifdef THREAD_LOCKING + sys_unlock(); +#endif + didsomething = 1; + } + return (didsomething); + } + else + { +#ifdef _WIN32 + if (pd_this->pd_inter->i_maxfd == 0) + Sleep(microsec/1000); + else +#endif + select(0, 0, 0, 0, &timout); + return (0); + } +} + +void sys_microsleep(int microsec) +{ + sys_domicrosleep(microsec, 1); +} + +#if !defined(_WIN32) && !defined(__CYGWIN__) +static void sys_signal(int signo, sig_t sigfun) +{ + struct sigaction action; + action.sa_flags = 0; + action.sa_handler = sigfun; + memset(&action.sa_mask, 0, sizeof(action.sa_mask)); +#if 0 /* GG says: don't use that */ + action.sa_restorer = 0; +#endif + if (sigaction(signo, &action, 0) < 0) + perror("sigaction"); +} + +static void sys_exithandler(int n) +{ + static int trouble = 0; + if (!trouble) + { + trouble = 1; + fprintf(stderr, "Pd: signal %d\n", n); + sys_bail(1); + } + else _exit(1); +} + +static void sys_alarmhandler(int n) +{ + fprintf(stderr, "Pd: system call timed out\n"); +} + +static void sys_huphandler(int n) +{ + struct timeval timout; + timout.tv_sec = 0; + timout.tv_usec = 30000; + select(1, 0, 0, 0, &timout); +} + +void sys_setalarm(int microsec) +{ + struct itimerval gonzo; + int sec = (int)(microsec/1000000); + microsec %= 1000000; +#if 0 + fprintf(stderr, "timer %d:%d\n", sec, microsec); +#endif + gonzo.it_interval.tv_sec = 0; + gonzo.it_interval.tv_usec = 0; + gonzo.it_value.tv_sec = sec; + gonzo.it_value.tv_usec = microsec; + if (microsec) + sys_signal(SIGALRM, sys_alarmhandler); + else sys_signal(SIGALRM, SIG_IGN); + setitimer(ITIMER_REAL, &gonzo, 0); +} + +#endif /* NOT _WIN32 && NOT __CYGWIN__ */ + + /* on startup, set various signal handlers */ +void sys_setsignalhandlers( void) +{ +#if !defined(_WIN32) && !defined(__CYGWIN__) + signal(SIGHUP, sys_huphandler); + signal(SIGINT, sys_exithandler); + signal(SIGQUIT, sys_exithandler); + signal(SIGILL, sys_exithandler); +# ifdef SIGIOT + signal(SIGIOT, sys_exithandler); +# endif + signal(SIGFPE, SIG_IGN); + /* signal(SIGILL, sys_exithandler); + signal(SIGBUS, sys_exithandler); + signal(SIGSEGV, sys_exithandler); */ + signal(SIGPIPE, SIG_IGN); + signal(SIGALRM, SIG_IGN); +#if 0 /* GG says: don't use that */ + signal(SIGSTKFLT, sys_exithandler); +#endif +#endif /* NOT _WIN32 && NOT __CYGWIN__ */ +} + +#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__) + +#if defined(_POSIX_PRIORITY_SCHEDULING) || defined(_POSIX_MEMLOCK) +#include +#endif + +#define MODE_NRT 0 +#define MODE_RT 1 +#define MODE_WATCHDOG 2 + +void sys_set_priority(int mode) +{ +#ifdef _POSIX_PRIORITY_SCHEDULING + struct sched_param par; + int p1, p2, p3; + p1 = sched_get_priority_min(SCHED_FIFO); + p2 = sched_get_priority_max(SCHED_FIFO); +#ifdef USEAPI_JACK + p3 = (mode == MODE_WATCHDOG ? p1 + 7 : (mode == MODE_RT ? p1 + 5 : 0)); +#else + p3 = (mode == MODE_WATCHDOG ? p2 - 5 : (mode == MODE_RT ? p2 - 7 : 0)); +#endif + par.sched_priority = p3; + if (sched_setscheduler(0, + (mode == MODE_NRT ? SCHED_OTHER : SCHED_FIFO), &par) < 0) + { + if (mode == MODE_WATCHDOG) + fprintf(stderr, "priority %d scheduling failed.\n", p3); + else post("priority %d scheduling failed; running at normal priority", + p3); + } + else if (sys_verbose) + { + if (mode == MODE_RT) + post("priority %d scheduling enabled.\n", p3); + else post("running at normal (non-real-time) priority.\n"); + } +#endif + +#if !defined(USEAPI_JACK) + if (mode != MODE_NRT) + { + /* tb: force memlock to physical memory { */ + struct rlimit mlock_limit; + mlock_limit.rlim_cur=0; + mlock_limit.rlim_max=0; + setrlimit(RLIMIT_MEMLOCK,&mlock_limit); + /* } tb */ + if (mlockall(MCL_FUTURE) != -1 && sys_verbose) + fprintf(stderr, "memory locking enabled.\n"); + } + else munlockall(); +#endif +} + +#endif /* __linux__ */ + +/* ------------------ receiving incoming messages over sockets ------------- */ + +void sys_sockerror(char *s) +{ +#ifdef _WIN32 + int err = WSAGetLastError(); + if (err == 10054) return; + else if (err == 10044) + { + fprintf(stderr, + "Warning: you might not have TCP/IP \"networking\" turned on\n"); + fprintf(stderr, "which is needed for Pd to talk to its GUI layer.\n"); + } +#else + int err = errno; +#endif + error("%s: %s (%d)\n", s, strerror(err), err); +} + +void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr) +{ + int nfd, size; + t_fdpoll *fp; + sys_init_fdpoll(); + nfd = pd_this->pd_inter->i_nfdpoll; + size = nfd * sizeof(t_fdpoll); + pd_this->pd_inter->i_fdpoll = (t_fdpoll *)t_resizebytes( + pd_this->pd_inter->i_fdpoll, size, size + sizeof(t_fdpoll)); + fp = pd_this->pd_inter->i_fdpoll + nfd; + fp->fdp_fd = fd; + fp->fdp_fn = fn; + fp->fdp_ptr = ptr; + pd_this->pd_inter->i_nfdpoll = nfd + 1; + if (fd >= pd_this->pd_inter->i_maxfd) + pd_this->pd_inter->i_maxfd = fd + 1; +} + +void sys_rmpollfn(int fd) +{ + int nfd = pd_this->pd_inter->i_nfdpoll; + int i, size = nfd * sizeof(t_fdpoll); + t_fdpoll *fp; + for (i = nfd, fp = pd_this->pd_inter->i_fdpoll; i--; fp++) + { + if (fp->fdp_fd == fd) + { + while (i--) + { + fp[0] = fp[1]; + fp++; + } + pd_this->pd_inter->i_fdpoll = (t_fdpoll *)t_resizebytes( + pd_this->pd_inter->i_fdpoll, size, size - sizeof(t_fdpoll)); + pd_this->pd_inter->i_nfdpoll = nfd - 1; + return; + } + } + post("warning: %d removed from poll list but not found", fd); +} + +t_socketreceiver *socketreceiver_new(void *owner, t_socketnotifier notifier, + t_socketreceivefn socketreceivefn, int udp) +{ + t_socketreceiver *x = (t_socketreceiver *)getbytes(sizeof(*x)); + x->sr_inhead = x->sr_intail = 0; + x->sr_owner = owner; + x->sr_notifier = notifier; + x->sr_socketreceivefn = socketreceivefn; + x->sr_udp = udp; + if (!(x->sr_inbuf = malloc(INBUFSIZE))) bug("t_socketreceiver");; + return (x); +} + +void socketreceiver_free(t_socketreceiver *x) +{ + free(x->sr_inbuf); + freebytes(x, sizeof(*x)); +} + + /* this is in a separately called subroutine so that the buffer isn't + sitting on the stack while the messages are getting passed. */ +static int socketreceiver_doread(t_socketreceiver *x) +{ + char messbuf[INBUFSIZE], *bp = messbuf; + int indx, first = 1; + int inhead = x->sr_inhead; + int intail = x->sr_intail; + char *inbuf = x->sr_inbuf; + for (indx = intail; first || (indx != inhead); + first = 0, (indx = (indx+1)&(INBUFSIZE-1))) + { + /* if we hit a semi that isn't preceded by a \, it's a message + boundary. LATER we should deal with the possibility that the + preceding \ might itself be escaped! */ + char c = *bp++ = inbuf[indx]; + if (c == ';' && (!indx || inbuf[indx-1] != '\\')) + { + intail = (indx+1)&(INBUFSIZE-1); + binbuf_text(pd_this->pd_inter->i_inbinbuf, messbuf, bp - messbuf); + if (sys_debuglevel & DEBUG_MESSDOWN) + { + write(2, messbuf, bp - messbuf); + write(2, "\n", 1); + } + x->sr_inhead = inhead; + x->sr_intail = intail; + return (1); + } + } + return (0); +} + +static void socketreceiver_getudp(t_socketreceiver *x, int fd) +{ + char buf[INBUFSIZE+1]; + int ret = (int)recv(fd, buf, INBUFSIZE, 0); + if (ret < 0) + { + sys_sockerror("recv"); + sys_rmpollfn(fd); + sys_closesocket(fd); + } + else if (ret > 0) + { + buf[ret] = 0; +#if 0 + post("%s", buf); +#endif + if (buf[ret-1] != '\n') + { +#if 0 + buf[ret] = 0; + error("dropped bad buffer %s\n", buf); +#endif + } + else + { + char *semi = strchr(buf, ';'); + if (semi) + *semi = 0; + binbuf_text(pd_this->pd_inter->i_inbinbuf, buf, strlen(buf)); + outlet_setstacklim(); + if (x->sr_socketreceivefn) + (*x->sr_socketreceivefn)(x->sr_owner, + pd_this->pd_inter->i_inbinbuf); + else bug("socketreceiver_getudp"); + } + } +} + +void sys_exit(void); + +void socketreceiver_read(t_socketreceiver *x, int fd) +{ + if (x->sr_udp) /* UDP ("datagram") socket protocol */ + socketreceiver_getudp(x, fd); + else /* TCP ("streaming") socket protocol */ + { + char *semi; + int readto = + (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1); + int ret; + + /* the input buffer might be full. If so, drop the whole thing */ + if (readto == x->sr_inhead) + { + fprintf(stderr, "pd: dropped message from gui\n"); + x->sr_inhead = x->sr_intail = 0; + readto = INBUFSIZE; + } + else + { + ret = (int)recv(fd, x->sr_inbuf + x->sr_inhead, + readto - x->sr_inhead, 0); + if (ret <= 0) + { + if (ret < 0) + sys_sockerror("recv"); + if (x == pd_this->pd_inter->i_socketreceiver) + { + if (pd_this == &pd_maininstance) + sys_bail(1); + else + { + sys_rmpollfn(fd); + sys_closesocket(fd); + sys_stopgui(); + } + } + else + { + if (x->sr_notifier) + (*x->sr_notifier)(x->sr_owner, fd); + sys_rmpollfn(fd); + sys_closesocket(fd); + } + } + else + { + x->sr_inhead += ret; + if (x->sr_inhead >= INBUFSIZE) x->sr_inhead = 0; + while (socketreceiver_doread(x)) + { + outlet_setstacklim(); + if (x->sr_socketreceivefn) + (*x->sr_socketreceivefn)(x->sr_owner, + pd_this->pd_inter->i_inbinbuf); + else binbuf_eval(pd_this->pd_inter->i_inbinbuf, 0, 0, 0); + if (x->sr_inhead == x->sr_intail) + break; + } + } + } + } +} + +void sys_closesocket(int fd) +{ +#ifdef HAVE_UNISTD_H + if(fd<0) + return; + close(fd); +#endif +#ifdef _WIN32 + closesocket(fd); +#endif +} + +/* ---------------------- sending messages to the GUI ------------------ */ +#define GUI_ALLOCCHUNK 8192 +#define GUI_UPDATESLICE 512 /* how much we try to do in one idle period */ +#define GUI_BYTESPERPING 1024 /* how much we send up per ping */ + +static void sys_trytogetmoreguibuf(int newsize) +{ + char *newbuf = realloc(pd_this->pd_inter->i_guibuf, newsize); +#if 0 + static int sizewas; + if (newsize > 70000 && sizewas < 70000) + { + int i; + for (i = pd_this->pd_inter->i_guitail; + i < pd_this->pd_inter->i_guihead; i++) + fputc(pd_this->pd_inter->i_guibuf[i], stderr); + } + sizewas = newsize; +#endif +#if 0 + fprintf(stderr, "new size %d (head %d, tail %d)\n", + newsize, pd_this->pd_inter->i_guihead, pd_this->pd_inter->i_guitail); +#endif + + /* if realloc fails, make a last-ditch attempt to stay alive by + synchronously writing out the existing contents. LATER test + this by intentionally setting newbuf to zero */ + if (!newbuf) + { + int bytestowrite = pd_this->pd_inter->i_guitail - + pd_this->pd_inter->i_guihead; + int written = 0; + while (1) + { + int res = (int)send(pd_this->pd_inter->i_guisock, + pd_this->pd_inter->i_guibuf + pd_this->pd_inter->i_guitail + + written, bytestowrite, 0); + if (res < 0) + { + perror("pd output pipe"); + sys_bail(1); + } + else + { + written += res; + if (written >= bytestowrite) + break; + } + } + pd_this->pd_inter->i_guihead = pd_this->pd_inter->i_guitail = 0; + } + else + { + pd_this->pd_inter->i_guisize = newsize; + pd_this->pd_inter->i_guibuf = newbuf; + } +} + +int sys_havegui( void) +{ + return (pd_this->pd_inter->i_havegui); +} + +void sys_vgui(char *fmt, ...) +{ + int msglen, bytesleft, headwas, nwrote; + va_list ap; + + if (!sys_havegui()) + return; + if (!pd_this->pd_inter->i_guibuf) + { + if (!(pd_this->pd_inter->i_guibuf = malloc(GUI_ALLOCCHUNK))) + { + fprintf(stderr, "Pd: couldn't allocate GUI buffer\n"); + sys_bail(1); + } + pd_this->pd_inter->i_guisize = GUI_ALLOCCHUNK; + pd_this->pd_inter->i_guihead = pd_this->pd_inter->i_guitail = 0; + } + if (pd_this->pd_inter->i_guihead > pd_this->pd_inter->i_guisize - + (GUI_ALLOCCHUNK/2)) + sys_trytogetmoreguibuf(pd_this->pd_inter->i_guisize + + GUI_ALLOCCHUNK); + va_start(ap, fmt); + msglen = vsnprintf(pd_this->pd_inter->i_guibuf + + pd_this->pd_inter->i_guihead, + pd_this->pd_inter->i_guisize - pd_this->pd_inter->i_guihead, + fmt, ap); + va_end(ap); + if(msglen < 0) + { + fprintf(stderr, + "Pd: buffer space wasn't sufficient for long GUI string\n"); + return; + } + if (msglen >= pd_this->pd_inter->i_guisize - pd_this->pd_inter->i_guihead) + { + int msglen2, newsize = pd_this->pd_inter->i_guisize + 1 + + (msglen > GUI_ALLOCCHUNK ? msglen : GUI_ALLOCCHUNK); + sys_trytogetmoreguibuf(newsize); + + va_start(ap, fmt); + msglen2 = vsnprintf(pd_this->pd_inter->i_guibuf + + pd_this->pd_inter->i_guihead, + pd_this->pd_inter->i_guisize - pd_this->pd_inter->i_guihead, + fmt, ap); + va_end(ap); + if (msglen2 != msglen) + bug("sys_vgui"); + if (msglen >= pd_this->pd_inter->i_guisize - + pd_this->pd_inter->i_guihead) msglen = + pd_this->pd_inter->i_guisize - pd_this->pd_inter->i_guihead; + } + if (sys_debuglevel & DEBUG_MESSUP) + fprintf(stderr, "%s", + pd_this->pd_inter->i_guibuf + pd_this->pd_inter->i_guihead); + pd_this->pd_inter->i_guihead += msglen; + pd_this->pd_inter->i_bytessincelastping += msglen; +} + +void sys_gui(char *s) +{ + sys_vgui("%s", s); +} + +static int sys_flushtogui(void) +{ + int writesize = pd_this->pd_inter->i_guihead - pd_this->pd_inter->i_guitail, + nwrote = 0; + if (writesize > 0) + nwrote = (int)send(pd_this->pd_inter->i_guisock, + pd_this->pd_inter->i_guibuf + pd_this->pd_inter->i_guitail, + writesize, 0); + +#if 0 + if (writesize) + fprintf(stderr, "wrote %d of %d\n", nwrote, writesize); +#endif + + if (nwrote < 0) + { + perror("pd-to-gui socket"); + sys_bail(1); + } + else if (!nwrote) + return (0); + else if (nwrote >= pd_this->pd_inter->i_guihead - + pd_this->pd_inter->i_guitail) + pd_this->pd_inter->i_guihead = pd_this->pd_inter->i_guitail = 0; + else if (nwrote) + { + pd_this->pd_inter->i_guitail += nwrote; + if (pd_this->pd_inter->i_guitail > (pd_this->pd_inter->i_guisize >> 2)) + { + memmove(pd_this->pd_inter->i_guibuf, + pd_this->pd_inter->i_guibuf + pd_this->pd_inter->i_guitail, + pd_this->pd_inter->i_guihead - + pd_this->pd_inter->i_guitail); + pd_this->pd_inter->i_guihead = pd_this->pd_inter->i_guihead - + pd_this->pd_inter->i_guitail; + pd_this->pd_inter->i_guitail = 0; + } + } + return (1); +} + +void glob_ping(t_pd *dummy) +{ + pd_this->pd_inter->i_waitingforping = 0; +} + +static int sys_flushqueue(void ) +{ + int wherestop = pd_this->pd_inter->i_bytessincelastping + GUI_UPDATESLICE; + if (wherestop + (GUI_UPDATESLICE >> 1) > GUI_BYTESPERPING) + wherestop = 0x7fffffff; + if (pd_this->pd_inter->i_waitingforping) + return (0); + if (!pd_this->pd_inter->i_guiqueuehead) + return (0); + while (1) + { + if (pd_this->pd_inter->i_bytessincelastping >= GUI_BYTESPERPING) + { + sys_gui("pdtk_ping\n"); + pd_this->pd_inter->i_bytessincelastping = 0; + pd_this->pd_inter->i_waitingforping = 1; + return (1); + } + if (pd_this->pd_inter->i_guiqueuehead) + { + t_guiqueue *headwas = pd_this->pd_inter->i_guiqueuehead; + pd_this->pd_inter->i_guiqueuehead = headwas->gq_next; + (*headwas->gq_fn)(headwas->gq_client, headwas->gq_glist); + t_freebytes(headwas, sizeof(*headwas)); + if (pd_this->pd_inter->i_bytessincelastping >= wherestop) + break; + } + else break; + } + sys_flushtogui(); + return (1); +} + + /* flush output buffer and update queue to gui in small time slices */ +static int sys_poll_togui(void) /* returns 1 if did anything */ +{ + if (!sys_havegui()) + return (0); + /* in case there is stuff still in the buffer, try to flush it. */ + sys_flushtogui(); + /* if the flush wasn't complete, wait. */ + if (pd_this->pd_inter->i_guihead > pd_this->pd_inter->i_guitail) + return (0); + + /* check for queued updates */ + if (sys_flushqueue()) + return (1); + + return (0); +} + + /* if some GUI object is having to do heavy computations, it can tell + us to back off from doing more updates by faking a big one itself. */ +void sys_pretendguibytes(int n) +{ + pd_this->pd_inter->i_bytessincelastping += n; +} + +void sys_queuegui(void *client, t_glist *glist, t_guicallbackfn f) +{ + t_guiqueue **gqnextptr, *gq; + if (!pd_this->pd_inter->i_guiqueuehead) + gqnextptr = &pd_this->pd_inter->i_guiqueuehead; + else + { + for (gq = pd_this->pd_inter->i_guiqueuehead; gq->gq_next; + gq = gq->gq_next) + if (gq->gq_client == client) + return; + if (gq->gq_client == client) + return; + gqnextptr = &gq->gq_next; + } + gq = t_getbytes(sizeof(*gq)); + gq->gq_next = 0; + gq->gq_client = client; + gq->gq_glist = glist; + gq->gq_fn = f; + gq->gq_next = 0; + *gqnextptr = gq; +} + +void sys_unqueuegui(void *client) +{ + t_guiqueue *gq, *gq2; + while (pd_this->pd_inter->i_guiqueuehead && + pd_this->pd_inter->i_guiqueuehead->gq_client == client) + { + gq = pd_this->pd_inter->i_guiqueuehead; + pd_this->pd_inter->i_guiqueuehead = + pd_this->pd_inter->i_guiqueuehead->gq_next; + t_freebytes(gq, sizeof(*gq)); + } + if (!pd_this->pd_inter->i_guiqueuehead) + return; + for (gq = pd_this->pd_inter->i_guiqueuehead; (gq2 = gq->gq_next); gq = gq2) + if (gq2->gq_client == client) + { + gq->gq_next = gq2->gq_next; + t_freebytes(gq2, sizeof(*gq2)); + break; + } +} + +int sys_pollgui(void) +{ + return (sys_domicrosleep(0, 1) || sys_poll_togui()); +} + +void sys_init_fdpoll(void) +{ + if (pd_this->pd_inter->i_fdpoll) + return; + /* create an empty FD poll list */ + pd_this->pd_inter->i_fdpoll = (t_fdpoll *)t_getbytes(0); + pd_this->pd_inter->i_nfdpoll = 0; + pd_this->pd_inter->i_inbinbuf = binbuf_new(); +} + +/* --------------------- starting up the GUI connection ------------- */ + +static int sys_watchfd; + +#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__) +void glob_watchdog(t_pd *dummy) +{ + if (write(sys_watchfd, "\n", 1) < 1) + { + fprintf(stderr, "pd: watchdog process died\n"); + sys_bail(1); + } +} +#endif + +static void sys_init_deken( void) +{ + const char*os = +#if defined __linux__ + "Linux" +#elif defined __APPLE__ + "Darwin" +#elif defined __FreeBSD__ + "FreeBSD" +#elif defined __NetBSD__ + "NetBSD" +#elif defined __OpenBSD__ + "OpenBSD" +#elif defined _WIN32 + "Windows" +#else +# if defined(__GNUC__) +# warning unknown OS +# endif + 0 +#endif + ; + const char*machine = +#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) || defined(_M_AMD64) + "amd64" +#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(_M_IX86) + "i386" +#elif defined(__ppc__) + "ppc" +#elif defined(__aarch64__) + "arm64" +#elif defined (__ARM_ARCH) + "armv" stringify(__ARM_ARCH) +# if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) +# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + "b" +# endif +# endif +#else +# if defined(__GNUC__) +# warning unknown architecture +# endif + 0 +#endif + ; + + /* only send the arch info, if we are sure about it... */ + if (os && machine) + sys_vgui("::deken::set_platform %s %s %d %d\n", + os, machine, + 8 * sizeof(char*), + 8 * sizeof(t_float)); +} + +#define FIRSTPORTNUM 5400 + +static int sys_do_startgui(const char *libdir) +{ + char cmdbuf[4*MAXPDSTRING], *guicmd, apibuf[256], apibuf2[256]; + struct sockaddr_in server = {0}; + int msgsock; + char buf[15]; + int len = sizeof(server); + const int maxtry = 20; + int ntry = 0, portno = FIRSTPORTNUM; + int xsock = -1, dumbo = -1; +#ifdef _WIN32 + short version = MAKEWORD(2, 0); + WSADATA nobby; +#else + int stdinpipe[2]; + pid_t childpid; +#endif /* _WIN32 */ + + sys_init_fdpoll(); + +#ifdef _WIN32 + if (WSAStartup(version, &nobby)) sys_sockerror("WSAstartup"); +#endif /* _WIN32 */ + + if (sys_guisetportnumber) /* GUI exists and sent us a port number */ + { + struct sockaddr_in server = {0}; + struct hostent *hp; +#ifdef __APPLE__ + /* guisock might be 1 or 2, which will have offensive results + if somebody writes to stdout or stderr - so we just open a few + files to try to fill fds 0 through 2. (I tried using dup() + instead, which would seem the logical way to do this, but couldn't + get it to work.) */ + int burnfd1 = open("/dev/null", 0), burnfd2 = open("/dev/null", 0), + burnfd3 = open("/dev/null", 0); + if (burnfd1 > 2) + close(burnfd1); + if (burnfd2 > 2) + close(burnfd2); + if (burnfd3 > 2) + close(burnfd3); +#endif + /* create a socket */ + pd_this->pd_inter->i_guisock = socket(AF_INET, SOCK_STREAM, 0); + if (pd_this->pd_inter->i_guisock < 0) + sys_sockerror("socket"); + + /* connect socket using hostname provided in command line */ + server.sin_family = AF_INET; + + hp = gethostbyname(LOCALHOST); + + if (hp == 0) + { + fprintf(stderr, + "localhost not found (inet protocol not installed?)\n"); + return (1); + } + memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); + + /* assign client port number */ + server.sin_port = htons((unsigned short)sys_guisetportnumber); + + /* try to connect */ + if (connect(pd_this->pd_inter->i_guisock, + (struct sockaddr *) &server, sizeof (server)) < 0) + { + sys_sockerror("connecting stream socket"); + return (1); + } + } + else /* default behavior: start up the GUI ourselves. */ + { +#ifdef _WIN32 + char scriptbuf[MAXPDSTRING+30], wishbuf[MAXPDSTRING+30], portbuf[80]; + int spawnret; + char intarg; +#else + int intarg; +#endif + + /* create a socket */ + xsock = socket(AF_INET, SOCK_STREAM, 0); + if (xsock < 0) + { + sys_sockerror("socket"); + return (1); + } + intarg = 1; + if (setsockopt(xsock, IPPROTO_TCP, TCP_NODELAY, + &intarg, sizeof(intarg)) < 0) +#ifndef _WIN32 + post("setsockopt (TCP_NODELAY) failed\n") +#endif + ; + + + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + + /* assign server port number */ + server.sin_port = htons((unsigned short)portno); + /* name the socket */ + while (bind(xsock, (struct sockaddr *)&server, sizeof(server)) < 0) + { +#ifdef _WIN32 + int err = WSAGetLastError(); +#else + int err = errno; +#endif + if ((ntry++ > maxtry) || (err != EADDRINUSE)) + { + perror("bind"); + fprintf(stderr, + "Pd was unable to find a port number to bind to\n"); + sys_closesocket(xsock); + return (1); + } else if (ntry > maxtry) { + /* last try: let the system pick a random port for us */ + portno = 0; + } else + portno++; + server.sin_port = htons((unsigned short)(portno)); + } + if (!portno) { + /* if the system chose a port for us, we need to know which */ + socklen_t serversize=sizeof(server); + if(!getsockname(xsock, (struct sockaddr *)&server, &serversize)) + portno = ntohs(server.sin_port); + } + if (sys_verbose) fprintf(stderr, "port %d\n", portno); + + +#ifndef _WIN32 + if (sys_guicmd) + guicmd = sys_guicmd; + else + { +#ifdef __APPLE__ + int i; + struct stat statbuf; + glob_t glob_buffer; + char *homedir = getenv("HOME"); + char embed_glob[FILENAME_MAX]; + char home_filename[FILENAME_MAX]; + char *wish_paths[11] = { + "(custom wish not defined)", + "(did not find a home directory)", + "/Applications/Utilities/Wish.app/Contents/MacOS/Wish", + "/Applications/Utilities/Wish Shell.app/Contents/MacOS/Wish Shell", + "/Applications/Wish.app/Contents/MacOS/Wish", + "/Applications/Wish Shell.app/Contents/MacOS/Wish Shell", + "/Library/Frameworks/Tk.framework/Resources/Wish.app/Contents/MacOS/Wish", + "/Library/Frameworks/Tk.framework/Resources/Wish Shell.app/Contents/MacOS/Wish Shell", + "/System/Library/Frameworks/Tk.framework/Resources/Wish.app/Contents/MacOS/Wish", + "/System/Library/Frameworks/Tk.framework/Resources/Wish Shell.app/Contents/MacOS/Wish Shell", + "/usr/bin/wish" + }; + /* this glob is needed so the Wish executable can have the same + * filename as the Pd.app, i.e. 'Pd-0.42-3.app' should have a Wish + * executable called 'Pd-0.42-3.app/Contents/MacOS/Pd-0.42-3' */ + sprintf(embed_glob, "%s/../MacOS/Pd*", libdir); + glob_buffer.gl_matchc = 1; /* we only need one match */ + glob(embed_glob, GLOB_LIMIT, NULL, &glob_buffer); + /* If we are using a copy of Wish embedded in the Pd.app, then it + * will automatically load pd-gui.tcl if that embedded Wish can + * find ../Resources/Scripts/AppMain.tcl, then Wish doesn't want + * to receive the pd-gui.tcl as an argument. Otherwise it needs + * to know how to find pd-gui.tcl */ + if (glob_buffer.gl_pathc > 0) + sprintf(cmdbuf, "\"%s\" %d\n", glob_buffer.gl_pathv[0], portno); + else + { + #ifdef WISH + wish_paths[0] = WISH; + #endif + sprintf(home_filename, + "%s/Applications/Wish.app/Contents/MacOS/Wish",homedir); + wish_paths[1] = home_filename; + for(i=0; i<11; i++) + { + if (sys_verbose) + fprintf(stderr, "Trying Wish at \"%s\"\n", + wish_paths[i]); + if (stat(wish_paths[i], &statbuf) >= 0) + break; + } + sprintf(cmdbuf, "\"%s\" \"%s/%spd-gui.tcl\" %d\n", + wish_paths[i], libdir, PDGUIDIR, portno); + } +#else /* __APPLE__ */ + /* sprintf the wish command with needed environment variables. + For some reason the wish script fails if HOME isn't defined so + if necessary we put that in here too. */ + sprintf(cmdbuf, + "TCL_LIBRARY=\"%s/lib/tcl/library\" TK_LIBRARY=\"%s/lib/tk/library\"%s \ + " WISH " \"%s/" PDGUIDIR "/pd-gui.tcl\" %d\n", + libdir, libdir, (getenv("HOME") ? "" : " HOME=/tmp"), + libdir, portno); +#endif /* __APPLE__ */ + guicmd = cmdbuf; + } + if (sys_verbose) + fprintf(stderr, "%s", guicmd); + + childpid = fork(); + if (childpid < 0) + { + if (errno) perror("sys_startgui"); + else fprintf(stderr, "sys_startgui failed\n"); + sys_closesocket(xsock); + return (1); + } + else if (!childpid) /* we're the child */ + { + sys_closesocket(xsock); /* child doesn't listen */ +#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__) + sys_set_priority(MODE_NRT); /* child runs non-real-time */ +#endif +#ifndef __APPLE__ +// TODO this seems unneeded on any platform hans@eds.org + /* the wish process in Unix will make a wish shell and + read/write standard in and out unless we close the + file descriptors. Somehow this doesn't make the MAC OSX + version of Wish happy...*/ + if (pipe(stdinpipe) < 0) + sys_sockerror("pipe"); + else + { + if (stdinpipe[0] != 0) + { + close (0); + dup2(stdinpipe[0], 0); + close(stdinpipe[0]); + } + } +#endif /* NOT __APPLE__ */ + execl("/bin/sh", "sh", "-c", guicmd, (char*)0); + perror("pd: exec"); + fprintf(stderr, "Perhaps tcl and tk aren't yet installed?\n"); + _exit(1); + } +#else /* NOT _WIN32 */ + /* fprintf(stderr, "%s\n", libdir); */ + + strcpy(scriptbuf, "\""); + strcat(scriptbuf, libdir); + strcat(scriptbuf, "/" PDGUIDIR "pd-gui.tcl\""); + sys_bashfilename(scriptbuf, scriptbuf); + + sprintf(portbuf, "%d", portno); + + strcpy(wishbuf, libdir); + strcat(wishbuf, "/" PDBINDIR WISH); + sys_bashfilename(wishbuf, wishbuf); + + spawnret = _spawnl(P_NOWAIT, wishbuf, WISH, scriptbuf, portbuf, 0); + if (spawnret < 0) + { + perror("spawnl"); + fprintf(stderr, "%s: couldn't load TCL\n", wishbuf); + return (1); + } + +#endif /* NOT _WIN32 */ + } + + + if (!sys_guisetportnumber) + { + if (sys_verbose) + fprintf(stderr, "Waiting for connection request... \n"); + if (listen(xsock, 5) < 0) sys_sockerror("listen"); + + pd_this->pd_inter->i_guisock = accept(xsock, + (struct sockaddr *) &server, (socklen_t *)&len); + + sys_closesocket(xsock); + + if (pd_this->pd_inter->i_guisock < 0) sys_sockerror("accept"); + if (sys_verbose) + fprintf(stderr, "... connected\n"); + pd_this->pd_inter->i_guihead = pd_this->pd_inter->i_guitail = 0; + } + + pd_this->pd_inter->i_socketreceiver = socketreceiver_new(0, 0, 0, 0); + sys_addpollfn(pd_this->pd_inter->i_guisock, + (t_fdpollfn)socketreceiver_read, + pd_this->pd_inter->i_socketreceiver); + + /* here is where we start the pinging. */ +#if defined(__linux__) || defined(__FreeBSD_kernel__) + if (sys_hipriority) + sys_gui("pdtk_watchdog\n"); +#endif + sys_get_audio_apis(apibuf); + sys_get_midi_apis(apibuf2); + sys_set_searchpath(); /* tell GUI about path and startup flags */ + sys_set_extrapath(); + sys_set_startup(); + /* ... and about font, medio APIS, etc */ + sys_vgui("pdtk_pd_startup %d %d %d {%s} %s %s {%s} %s\n", + PD_MAJOR_VERSION, PD_MINOR_VERSION, + PD_BUGFIX_VERSION, PD_TEST_VERSION, + apibuf, apibuf2, sys_font, sys_fontweight); + sys_vgui("set pd_whichapi %d\n", sys_audioapi); + sys_vgui("set zoom_open %d\n", sys_zoom_open == 2); + + sys_init_deken(); + return (0); +} + +void sys_setrealtime(const char *libdir) +{ + char cmdbuf[MAXPDSTRING]; +#if defined(__linux__) || defined(__FreeBSD_kernel__) + /* promote this process's priority, if we can and want to. + If sys_hipriority not specified (-1), we assume real-time was wanted. + Starting in Linux 2.6 one can permit real-time operation of Pd by] + putting lines like: + @audio - rtprio 99 + @audio - memlock unlimited + in the system limits file, perhaps /etc/limits.conf or + /etc/security/limits.conf, and calling Pd from a user in group audio. */ + if (sys_hipriority == -1) + sys_hipriority = 1; + + snprintf(cmdbuf, MAXPDSTRING, "%s/bin/pd-watchdog", libdir); + cmdbuf[MAXPDSTRING-1] = 0; + if (sys_hipriority) + { + struct stat statbuf; + if (stat(cmdbuf, &statbuf) < 0) + { + fprintf(stderr, + "disabling real-time priority due to missing pd-watchdog (%s)\n", + cmdbuf); + sys_hipriority = 0; + } + } + if (sys_hipriority) + { + int pipe9[2], watchpid; + /* To prevent lockup, we fork off a watchdog process with + higher real-time priority than ours. The GUI has to send + a stream of ping messages to the watchdog THROUGH the Pd + process which has to pick them up from the GUI and forward + them. If any of these things aren't happening the watchdog + starts sending "stop" and "cont" signals to the Pd process + to make it timeshare with the rest of the system. (Version + 0.33P2 : if there's no GUI, the watchdog pinging is done + from the scheduler idle routine in this process instead.) */ + + if (pipe(pipe9) < 0) + { + sys_sockerror("pipe"); + return; + } + watchpid = fork(); + if (watchpid < 0) + { + if (errno) + perror("sys_setpriority"); + else fprintf(stderr, "sys_setpriority failed\n"); + return; + } + else if (!watchpid) /* we're the child */ + { + sys_set_priority(MODE_WATCHDOG); + if (pipe9[1] != 0) + { + dup2(pipe9[0], 0); + close(pipe9[0]); + } + close(pipe9[1]); + + if (sys_verbose) fprintf(stderr, "%s\n", cmdbuf); + execl("/bin/sh", "sh", "-c", cmdbuf, (char*)0); + perror("pd: exec"); + _exit(1); + } + else /* we're the parent */ + { + sys_set_priority(MODE_RT); + close(pipe9[0]); + /* set close-on-exec so that watchdog will see an EOF when we + close our copy - otherwise it might hang waiting for some + stupid child process (as seems to happen if jackd auto-starts + for us.) */ + if(fcntl(pipe9[1], F_SETFD, FD_CLOEXEC) < 0) + perror("close-on-exec"); + sys_watchfd = pipe9[1]; + /* We also have to start the ping loop in the GUI; + this is done later when the socket is open. */ + } + } + else if (sys_verbose) + post("not setting real-time priority"); +#endif /* __linux__ */ + +#ifdef _WIN32 + if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) + fprintf(stderr, "pd: couldn't set high priority class\n"); +#endif +#ifdef __APPLE__ + if (sys_hipriority) + { + struct sched_param param; + int policy = SCHED_RR; + int err; + param.sched_priority = 80; /* adjust 0 : 100 */ + + err = pthread_setschedparam(pthread_self(), policy, ¶m); + if (err) + post("warning: high priority scheduling failed\n"); + } +#endif /* __APPLE__ */ +} + +extern void sys_exit(void); + +/* This is called when something bad has happened, like a segfault. +Call glob_quit() below to exit cleanly. +LATER try to save dirty documents even in the bad case. */ +void sys_bail(int n) +{ + static int reentered = 0; + if (!reentered) + { + reentered = 1; +#if !defined(__linux__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__) + /* sys_close_audio() hangs if you're in a signal? */ + fprintf(stderr ,"gui socket %d - ", pd_this->pd_inter->i_guisock); + fprintf(stderr, "closing audio...\n"); + sys_close_audio(); + fprintf(stderr, "closing MIDI...\n"); + sys_close_midi(); + fprintf(stderr, "... done.\n"); +#endif + exit(n); + } + else _exit(1); +} + +void glob_quit(void *dummy) +{ + sys_close_audio(); + sys_close_midi(); + if (sys_havegui()) + { + sys_closesocket(pd_this->pd_inter->i_guisock); + sys_rmpollfn(pd_this->pd_inter->i_guisock); + } + exit(0); +} + + /* recursively descend to all canvases and send them "vis" messages + if they believe they're visible, to make it really so. */ +static void glist_maybevis(t_glist *gl) +{ + t_gobj *g; + for (g = gl->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd) == canvas_class) + glist_maybevis((t_glist *)g); + if (gl->gl_havewindow) + { + canvas_vis(gl, 0); + canvas_vis(gl, 1); + } +} + +int sys_startgui(const char *libdir) +{ + t_canvas *x; + for (x = pd_getcanvaslist(); x; x = x->gl_next) + canvas_vis(x, 0); + pd_this->pd_inter->i_havegui = 1; + pd_this->pd_inter->i_guihead = pd_this->pd_inter->i_guitail = 0; + if (sys_do_startgui(libdir)) + return (-1); + for (x = pd_getcanvaslist(); x; x = x->gl_next) + if (strcmp(x->gl_name->s_name, "_float_template") && + strcmp(x->gl_name->s_name, "_float_array_template") && + strcmp(x->gl_name->s_name, "_text_template")) + { + glist_maybevis(x); + canvas_vis(x, 1); + } + return (0); +} + + /* more work needed here - for some reason we can't restart the gui after + shutting it down this way. I think the second 'init' message never makes + it because the to-gui buffer isn't re-initialized. */ +void sys_stopgui( void) +{ + t_canvas *x; + for (x = pd_getcanvaslist(); x; x = x->gl_next) + canvas_vis(x, 0); + sys_vgui("%s", "exit\n"); + if (pd_this->pd_inter->i_guisock >= 0) + { + sys_closesocket(pd_this->pd_inter->i_guisock); + sys_rmpollfn(pd_this->pd_inter->i_guisock); + pd_this->pd_inter->i_guisock = -1; + } + pd_this->pd_inter->i_havegui = 0; +} + +/* ----------- mutexes for thread safety --------------- */ + +void s_inter_newpdinstance( void) +{ + pd_this->pd_inter = getbytes(sizeof(*pd_this->pd_inter)); +#if PDTHREADS + pthread_mutex_init(&pd_this->pd_inter->i_mutex, NULL); + pd_this->pd_islocked = 0; +#endif +#ifdef _WIN32 + pd_this->pd_inter->i_freq = 0; +#endif + pd_this->pd_inter->i_havegui = 0; +} + +void s_inter_freepdinstance( void) +{ + freebytes(pd_this->pd_inter, sizeof(*pd_this->pd_inter)); +} + +#if PDTHREADS +#ifdef PDINSTANCE +static pthread_rwlock_t sys_rwlock = PTHREAD_RWLOCK_INITIALIZER; +#else /* PDINSTANCE */ +static pthread_mutex_t sys_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif /* PDINSTANCE */ +#endif /* PDTHREADS */ + +#if PDTHREADS + +/* routines to lock and unlock Pd's global class structure or list of Pd +instances. These are called internally within Pd when creating classes, adding +methods to them, or creating or freeing Pd instances. They should probably +not be called from outside Pd. They should be called at a point where the +current instance of Pd is currently locked via sys_lock() below; this gains +read access to the class and instance lists which must be released for the +write-lock to be available. */ + +void pd_globallock( void) +{ +#ifdef PDINSTANCE + if (!pd_this->pd_islocked) + bug("pd_globallock"); + pthread_rwlock_unlock(&sys_rwlock); + pthread_rwlock_wrlock(&sys_rwlock); +#endif /* PDINSTANCE */ +} + +void pd_globalunlock( void) +{ +#ifdef PDINSTANCE + pthread_rwlock_unlock(&sys_rwlock); + pthread_rwlock_rdlock(&sys_rwlock); +#endif /* PDINSTANCE */ +} + +/* routines to lock/unlock a Pd instance for thread safety. Call pd_setinsance +first. The "pd_this" variable can be written and read thread-safely as it +is defined as per-thread storage. */ +void sys_lock( void) +{ +#ifdef PDINSTANCE + pthread_mutex_lock(&pd_this->pd_inter->i_mutex); + pthread_rwlock_rdlock(&sys_rwlock); + pd_this->pd_islocked = 1; +#else + pthread_mutex_lock(&sys_mutex); +#endif +} + +void sys_unlock( void) +{ +#ifdef PDINSTANCE + pd_this->pd_islocked = 0; + pthread_rwlock_unlock(&sys_rwlock); + pthread_mutex_unlock(&pd_this->pd_inter->i_mutex); +#else + pthread_mutex_unlock(&sys_mutex); +#endif +} + +int sys_trylock( void) +{ +#ifdef PDINSTANCE + int ret; + if (!(ret = pthread_mutex_trylock(&pd_this->pd_inter->i_mutex))) + { + if (!(ret = pthread_rwlock_tryrdlock(&sys_rwlock))) + return (0); + else + { + pthread_mutex_unlock(&pd_this->pd_inter->i_mutex); + return (ret); + } + } + else return (ret); +#else + return pthread_mutex_trylock(&sys_mutex); +#endif +} + +#else /* PDTHREADS */ + +void sys_lock( void) {} +void sys_unlock( void) {} +void pd_globallock( void) {} +void pd_globalunlock( void) {} + +#endif /* PDTHREADS */ diff --git a/ports/camomile/source/LibPd/pure-data/src/s_loader.c b/ports/camomile/source/LibPd/pure-data/src/s_loader.c new file mode 100644 index 00000000..9ce02cfa --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_loader.c @@ -0,0 +1,492 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#if defined(HAVE_LIBDL) || defined(__FreeBSD__) +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#include +#include +#endif +#ifdef _WIN32 +#include +#include +#endif +#ifdef __APPLE__ +#include +#endif +#include +#include "m_pd.h" +#include "s_stuff.h" +#include +#include +#ifdef _MSC_VER /* This is only for Microsoft's compiler, not cygwin, e.g. */ +#define snprintf _snprintf +#define stat _stat +#endif + +typedef void (*t_xxx)(void); + +/* naming convention for externs. The names are kept distinct for those +who wish to make "fat" externs compiled for many platforms. Less specific +fallbacks are provided, primarily for back-compatibility; these suffice if +you are building a package which will run with a single set of compiled +objects. The specific name is the letter b, l, d, or m for BSD, linux, +darwin, or microsoft, followed by a more specific string, either "fat" for +a fat binary or an indication of the instruction set. */ + +#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__) || defined(__FreeBSD__) +static char sys_dllextent2[] = ".pd_linux"; +# ifdef __x86_64__ +static char sys_dllextent[] = ".l_ia64"; // this should be .l_x86_64 or .l_amd64 +# elif defined(__i386__) || defined(_M_IX86) +static char sys_dllextent[] = ".l_i386"; +# elif defined(__arm__) +static char sys_dllextent[] = ".l_arm"; +# else +static char sys_dllextent[] = ".so"; +# endif +#elif defined(__APPLE__) +# ifndef MACOSX3 +static char sys_dllextent[] = ".d_fat", sys_dllextent2[] = ".pd_darwin"; +# else +static char sys_dllextent[] = ".d_ppc", sys_dllextent2[] = ".pd_darwin"; +# endif +#elif defined(_WIN32) || defined(__CYGWIN__) +static char sys_dllextent[] = ".m_i386", sys_dllextent2[] = ".dll"; +#else +static char sys_dllextent[] = ".so", sys_dllextent2[] = ".so"; +#endif + + /* maintain list of loaded modules to avoid repeating loads */ +typedef struct _loadedlist +{ + struct _loadedlist *ll_next; + t_symbol *ll_name; +} t_loadlist; + +static t_loadlist *sys_loaded; +int sys_onloadlist(const char *classname) /* return true if already loaded */ +{ + t_symbol *s = gensym(classname); + t_loadlist *ll; + for (ll = sys_loaded; ll; ll = ll->ll_next) + if (ll->ll_name == s) + return (1); + return (0); +} + + /* add to list of loaded modules */ +void sys_putonloadlist(const char *classname) +{ + t_loadlist *ll = (t_loadlist *)getbytes(sizeof(*ll)); + ll->ll_name = gensym(classname); + ll->ll_next = sys_loaded; + sys_loaded = ll; + /* post("put on list %s", classname); */ +} + +void class_set_extern_dir(t_symbol *s); + +static int sys_do_load_abs(t_canvas *canvas, const char *objectname, + const char *path); +static int sys_do_load_lib(t_canvas *canvas, const char *objectname, + const char *path) +{ + char symname[MAXPDSTRING], filename[MAXPDSTRING], dirbuf[MAXPDSTRING], + *nameptr, altsymname[MAXPDSTRING]; + const char *classname, *cnameptr; + void *dlobj; + t_xxx makeout = NULL; + int i, hexmunge = 0, fd; +#ifdef _WIN32 + HINSTANCE ntdll; +#endif + /* NULL-path is only used as a last resort, + but we have already tried all paths */ + if(!path)return (0); + + if ((classname = strrchr(objectname, '/'))) + classname++; + else classname = objectname; + for (i = 0, cnameptr = classname; i < MAXPDSTRING-7 && *cnameptr; + cnameptr++) + { + char c = *cnameptr; + if ((c>='0' && c<='9') || (c>='A' && c<='Z')|| + (c>='a' && c<='z' )|| c == '_') + { + symname[i] = c; + i++; + } + /* trailing tilde becomes "_tilde" */ + else if (c == '~' && cnameptr[1] == 0) + { + strcpy(symname+i, "_tilde"); + i += strlen(symname+i); + } + else /* anything you can't put in a C symbol is sprintf'ed in hex */ + { + sprintf(symname+i, "0x%02x", c); + i += strlen(symname+i); + hexmunge = 1; + } + } + symname[i] = 0; + if (hexmunge) + { + memmove(symname+6, symname, strlen(symname)+1); + strncpy(symname, "setup_", 6); + } + else strcat(symname, "_setup"); + +#if 0 + fprintf(stderr, "lib: %s\n", classname); +#endif + /* try looking in the path for (objectname).(sys_dllextent) ... */ + if ((fd = sys_trytoopenone(path, objectname, sys_dllextent, + dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0) + goto gotone; + /* same, with the more generic sys_dllextent2 */ + if ((fd = sys_trytoopenone(path, objectname, sys_dllextent2, + dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0) + goto gotone; + /* next try (objectname)/(classname).(sys_dllextent) ... */ + strncpy(filename, objectname, MAXPDSTRING); + filename[MAXPDSTRING-2] = 0; + strcat(filename, "/"); + strncat(filename, classname, MAXPDSTRING-strlen(filename)); + filename[MAXPDSTRING-1] = 0; + if ((fd = sys_trytoopenone(path, filename, sys_dllextent, + dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0) + goto gotone; + if ((fd = sys_trytoopenone(path, filename, sys_dllextent2, + dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0) + goto gotone; +#ifdef ANDROID + /* Android libs have a 'lib' prefix, '.so' suffix and don't allow ~ */ + char libname[MAXPDSTRING] = "lib"; + strncat(libname, objectname, MAXPDSTRING - 4); + int len = strlen(libname); + if (libname[len-1] == '~' && len < MAXPDSTRING - 6) { + strcpy(libname+len-1, "_tilde"); + } + if ((fd = sys_trytoopenone(path, libname, ".so", + dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0) + goto gotone; +#endif + return (0); +gotone: + close(fd); + class_set_extern_dir(gensym(dirbuf)); + + /* rebuild the absolute pathname */ + strncpy(filename, dirbuf, MAXPDSTRING); + filename[MAXPDSTRING-2] = 0; + strcat(filename, "/"); + strncat(filename, nameptr, MAXPDSTRING-strlen(filename)); + filename[MAXPDSTRING-1] = 0; + +#ifdef _WIN32 + { + char dirname[MAXPDSTRING], *s, *basename; + sys_bashfilename(filename, filename); + /* set the dirname as DllDirectory, meaning in the path for + loading other DLLs so that dependent libraries can be included + in the same folder as the external. SetDllDirectory() needs a + minimum supported version of Windows XP SP1 for + SetDllDirectory, so WINVER must be 0x0502 */ + strncpy(dirname, filename, MAXPDSTRING); + s = strrchr(dirname, '\\'); + basename = s; + if (s && *s) + *s = '\0'; + if (!SetDllDirectory(dirname)) + error("Could not set '%s' as DllDirectory(), '%s' might not load.", + dirname, basename); + /* now load the DLL for the external */ + ntdll = LoadLibrary(filename); + if (!ntdll) + { + error("%s: couldn't load", filename); + class_set_extern_dir(&s_); + return (0); + } + makeout = (t_xxx)GetProcAddress(ntdll, symname); + if (!makeout) + makeout = (t_xxx)GetProcAddress(ntdll, "setup"); + SetDllDirectory(NULL); /* reset DLL dir to nothing */ + } +#elif defined(HAVE_LIBDL) || defined(__FreeBSD__) + dlobj = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); + if (!dlobj) + { + error("%s: %s", filename, dlerror()); + class_set_extern_dir(&s_); + return (0); + } + makeout = (t_xxx)dlsym(dlobj, symname); + if(!makeout) + makeout = (t_xxx)dlsym(dlobj, "setup"); +#else +#warning "No dynamic loading mechanism specified, \ + libdl or WIN32 required for loading externals!" +#endif + + if (!makeout) + { + error("load_object: Symbol \"%s\" not found", symname); + class_set_extern_dir(&s_); + return 0; + } + (*makeout)(); + class_set_extern_dir(&s_); + return (1); +} + + +/* linked list of loaders */ +typedef struct loader_queue { + loader_t loader; + struct loader_queue *next; +} loader_queue_t; + +static loader_queue_t loaders = {sys_do_load_lib, NULL}; + +/* register class loader function */ +void sys_register_loader(loader_t loader) +{ + loader_queue_t *q = &loaders; + while (1) + { + if (q->loader == loader) /* already loaded - nothing to do */ + return; + else if (q->next) + q = q->next; + else + { + q->next = (loader_queue_t *)getbytes(sizeof(loader_queue_t)); + q->next->loader = loader; + q->next->next = NULL; + break; + } + } +} + +#include "g_canvas.h" + +/* the data passed to the iter-function */ +struct _loadlib_data +{ + t_canvas *canvas; + const char *classname; + int ok; +}; + +int sys_loadlib_iter(const char *path, struct _loadlib_data *data) +{ + int ok = 0; + loader_queue_t *q; + for(q = &loaders; q; q = q->next) + if ((ok = q->loader(data->canvas, data->classname, path))) + break; + /* if all loaders failed, try to load as abstraction */ + if (!ok) + ok = sys_do_load_abs(data->canvas, data->classname, path); + data->ok = ok; + return (ok == 0); +} + +int sys_load_lib(t_canvas *canvas, const char *classname) +{ + int dspstate = canvas_suspend_dsp(); + struct _loadlib_data data; + data.canvas = canvas; + data.ok = 0; + + if (sys_onloadlist(classname)) + { + error("%s: already loaded", classname); + return (1); + } + /* if classname is absolute, try this first */ + if (sys_isabsolutepath(classname)) + { + /* this is just copied from sys_open_absolute() + LATER avoid code duplication */ + char dirbuf[MAXPDSTRING], *z = strrchr(classname, '/'); + int dirlen; + if (!z) + return (0); + dirlen = (int)(z - classname); + if (dirlen > MAXPDSTRING-1) + dirlen = MAXPDSTRING-1; + strncpy(dirbuf, classname, dirlen); + dirbuf[dirlen] = 0; + data.classname=classname+(dirlen+1); + sys_loadlib_iter(dirbuf, &data); + } + data.classname = classname; + if(!data.ok) + canvas_path_iterate(canvas, (t_canvas_path_iterator)sys_loadlib_iter, + &data); + + /* if loaders failed so far, we try a last time without a PATH + * let the loaders search wherever they want */ + if (!data.ok) + sys_loadlib_iter(0, &data); + + if(data.ok) + sys_putonloadlist(classname); + + + canvas_resume_dsp(dspstate); + return data.ok; +} + +int sys_run_scheduler(const char *externalschedlibname, + const char *sys_extraflagsstring) +{ + typedef int (*t_externalschedlibmain)(const char *); + t_externalschedlibmain externalmainfunc; + char filename[MAXPDSTRING]; + struct stat statbuf; + snprintf(filename, sizeof(filename), "%s%s", externalschedlibname, + sys_dllextent); + sys_bashfilename(filename, filename); + /* if first-choice file extent can't 'stat', go for second */ + if (stat(filename, &statbuf) < 0) + { + snprintf(filename, sizeof(filename), "%s%s", externalschedlibname, + sys_dllextent2); + sys_bashfilename(filename, filename); + } +#ifdef _WIN32 + { + HINSTANCE ntdll = LoadLibrary(filename); + if (!ntdll) + { + fprintf(stderr, "%s: couldn't load external scheduler\n", filename); + error("%s: couldn't load external scheduler", filename); + return (1); + } + externalmainfunc = + (t_externalschedlibmain)GetProcAddress(ntdll, "pd_extern_sched"); + if (!externalmainfunc) + externalmainfunc = + (t_externalschedlibmain)GetProcAddress(ntdll, "main"); + } +#elif defined HAVE_LIBDL + { + void *dlobj; + dlobj = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); + if (!dlobj) + { + error("%s: %s", filename, dlerror()); + fprintf(stderr, "dlopen failed for %s: %s\n", filename, dlerror()); + return (1); + } + externalmainfunc = (t_externalschedlibmain)dlsym(dlobj, + "pd_extern_sched"); + } +#else + return (0); +#endif + if (externalmainfunc) + return((*externalmainfunc)(sys_extraflagsstring)); + else + { + fprintf(stderr, "%s: couldn't find pd_extern_sched() or main()\n", + filename); + return (0); + } +} + + +/* abstraction loading */ +void canvas_popabstraction(t_canvas *x); +int pd_setloadingabstraction(t_symbol *sym); + +static t_pd *do_create_abstraction(t_symbol*s, int argc, t_atom *argv) +{ + /* + * TODO: check if the there is a binbuf cached for + and use that instead. We'll have to invalidate the cache once we + are done (either with a clock_delay(0) or something else) + */ + if (!pd_setloadingabstraction(s)) + { + const char *objectname = s->s_name; + char dirbuf[MAXPDSTRING], classslashclass[MAXPDSTRING], *nameptr; + t_glist *glist = (t_glist *)canvas_getcurrent(); + t_canvas *canvas = (t_canvas*)glist_getcanvas(glist); + int fd = -1; + + t_pd *was = s__X.s_thing; + snprintf(classslashclass, MAXPDSTRING, "%s/%s", objectname, objectname); + if ((fd = canvas_open(canvas, objectname, ".pd", + dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0 || + (fd = canvas_open(canvas, objectname, ".pat", + dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0 || + (fd = canvas_open(canvas, classslashclass, ".pd", + dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0) + { + close(fd); + canvas_setargs(argc, argv); + + binbuf_evalfile(gensym(nameptr), gensym(dirbuf)); + if (s__X.s_thing && was != s__X.s_thing) + canvas_popabstraction((t_canvas *)(s__X.s_thing)); + else s__X.s_thing = was; + canvas_setargs(0, 0); + return (pd_this->pd_newest); + } + /* otherwise we couldn't do it; just return 0 */ + } + else error("%s: can't load abstraction within itself\n", s->s_name); + pd_this->pd_newest = 0; + return (0); +} + +/* search for abstraction; register a creator if found */ +static int sys_do_load_abs(t_canvas *canvas, const char *objectname, + const char *path) +{ + int fd; + static t_gobj*abstraction_classes = 0; + char dirbuf[MAXPDSTRING], classslashclass[MAXPDSTRING], *nameptr; + /* NULL-path is only used as a last resort, + but we have already tried all paths */ + if (!path) return (0); + + snprintf(classslashclass, MAXPDSTRING, "%s/%s", objectname, objectname); + if ((fd = sys_trytoopenone(path, objectname, ".pd", + dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0 || + (fd = sys_trytoopenone(path, objectname, ".pat", + dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0 || + (fd = sys_trytoopenone(path, classslashclass, ".pd", + dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0) + { + t_class*c=0; + close(fd); + /* found an abstraction, now register it as a new pseudo-class */ + class_set_extern_dir(gensym(dirbuf)); + if((c=class_new(gensym(objectname), + (t_newmethod)do_create_abstraction, 0, + 0, 0, A_GIMME, 0))) + { + /* store away the newly created class, maybe we will need it one day */ + t_gobj*absclass=0; + absclass=t_getbytes(sizeof(*absclass)); + absclass->g_pd=c; + absclass->g_next=abstraction_classes; + abstraction_classes=absclass; + } + class_set_extern_dir(&s_); + + return (1); + } + return (0); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_main.c b/ports/camomile/source/LibPd/pure-data/src/s_main.c new file mode 100644 index 00000000..aaddb6b2 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_main.c @@ -0,0 +1,1469 @@ +/* Copyright (c) 1997-1999 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "m_imp.h" +#include "s_stuff.h" +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef _WIN32 +#include +#include +#include +#endif +#ifdef _MSC_VER /* This is only for Microsoft's compiler, not cygwin, e.g. */ +#define snprintf _snprintf +#endif + +#define stringify(s) str(s) +#define str(s) #s + +char *pd_version = "Pd-" stringify(PD_MAJOR_VERSION) "." \ +stringify(PD_MINOR_VERSION) "." stringify(PD_BUGFIX_VERSION) "\ + (" stringify(PD_TEST_VERSION) ")"; + +char pd_compiletime[] = __TIME__; +char pd_compiledate[] = __DATE__; + +void pd_init(void); +int sys_argparse(int argc, char **argv); +void sys_findprogdir(char *progname); +void sys_setsignalhandlers( void); +int sys_startgui(const char *guipath); +void sys_setrealtime(const char *guipath); +int m_mainloop(void); +int m_batchmain(void); +void sys_addhelppath(char *p); +#ifdef USEAPI_ALSA +void alsa_adddev(char *name); +#endif +int sys_oktoloadfiles(int done); + +int sys_debuglevel; +int sys_verbose; +int sys_noloadbang; +static int sys_dontstartgui; +int sys_hipriority = -1; /* -1 = not specified; 0 = no; 1 = yes */ +int sys_guisetportnumber; /* if started from the GUI, this is the port # */ +int sys_nosleep = 0; /* skip all "sleep" calls and spin instead */ +int sys_defeatrt; /* flag to cancel real-time */ +t_symbol *sys_flags; /* more command-line flags */ + +char *sys_guicmd; +t_symbol *sys_libdir; +static t_namelist *sys_openlist; +static t_namelist *sys_messagelist; +static int sys_version; +int sys_oldtclversion; /* hack to warn g_rtext.c about old text sel */ + +int sys_nmidiout = -1; +int sys_nmidiin = -1; +int sys_midiindevlist[MAXMIDIINDEV] = {1}; +int sys_midioutdevlist[MAXMIDIOUTDEV] = {1}; + +char sys_font[100] = "DejaVu Sans Mono"; +#if __APPLE__ +char sys_fontweight[10] = "normal"; +#else +char sys_fontweight[10] = "bold"; +#endif +static int sys_main_srate; +static int sys_main_advance; +static int sys_main_callback; +static int sys_main_blocksize; +static int sys_listplease; + +int sys_externalschedlib; +char sys_externalschedlibname[MAXPDSTRING]; +static int sys_batch; +int sys_extraflags; +char sys_extraflagsstring[MAXPDSTRING]; +int sys_run_scheduler(const char *externalschedlibname, + const char *sys_extraflagsstring); +int sys_noautopatch; /* temporary hack to defeat new 0.42 editing */ + + /* here the "-1" counts signify that the corresponding vector hasn't been + specified in command line arguments; sys_set_audio_settings will detect it + and fill things in. */ +static int sys_nsoundin = -1; +static int sys_nsoundout = -1; +static int sys_soundindevlist[MAXAUDIOINDEV]; +static int sys_soundoutdevlist[MAXAUDIOOUTDEV]; + +static int sys_nchin = -1; +static int sys_nchout = -1; +static int sys_chinlist[MAXAUDIOINDEV]; +static int sys_choutlist[MAXAUDIOOUTDEV]; + +t_sample* get_sys_soundout() { return STUFF->st_soundout; } +t_sample* get_sys_soundin() { return STUFF->st_soundin; } +int* get_sys_main_advance() { return &sys_main_advance; } +double* get_sys_time_per_dsp_tick() { return &STUFF->st_time_per_dsp_tick; } +int* get_sys_schedblocksize() { return &STUFF->st_schedblocksize; } +double* get_sys_time() { return &pd_this->pd_systime; } +t_float* get_sys_dacsr() { return &STUFF->st_dacsr; } +int* get_sys_sleepgrain() { return &sys_sleepgrain; } +int* get_sys_schedadvance() { return &sys_schedadvance; } +t_namelist *sys_searchpath; /* so old versions of GEM might compile */ +typedef struct _fontinfo +{ + int fi_pointsize; + int fi_width; + int fi_height; +} t_fontinfo; + + /* these give the nominal point size and maximum height of the characters + in the six fonts. */ + +static t_fontinfo sys_fontspec[] = { + {8, 5, 11}, {10, 6, 13}, {12, 7, 16}, + {16, 10, 19}, {24, 14, 29}, {36, 22, 44}}; +#define NFONT (sizeof(sys_fontspec)/sizeof(*sys_fontspec)) +#define NZOOM 2 +static t_fontinfo sys_gotfonts[NZOOM][NFONT]; + +/* here are the actual font size structs on msp's systems: +MSW: +font 8 5 9 8 5 11 +font 10 7 13 10 6 13 +font 12 9 16 14 8 16 +font 16 10 20 16 10 18 +font 24 15 25 16 10 18 +font 36 25 42 36 22 41 + +linux: +font 8 5 9 8 5 9 +font 10 7 13 12 7 13 +font 12 9 16 14 9 15 +font 16 10 20 16 10 19 +font 24 15 25 24 15 24 +font 36 25 42 36 22 41 +*/ + +static int sys_findfont(int fontsize) +{ + unsigned int i; + t_fontinfo *fi; + for (i = 0, fi = sys_fontspec; i < (NFONT-1); i++, fi++) + if (fontsize < fi[1].fi_pointsize) return (i); + return ((NFONT-1)); +} + +int sys_nearestfontsize(int fontsize) +{ + return (sys_fontspec[sys_findfont(fontsize)].fi_pointsize); +} + +int sys_hostfontsize(int fontsize, int zoom) +{ + zoom = (zoom < 1 ? 1 : (zoom > NZOOM ? NZOOM : zoom)); + return (sys_gotfonts[zoom-1][sys_findfont(fontsize)].fi_pointsize); +} + +int sys_zoomfontwidth(int fontsize, int zoomarg, int worstcase) +{ + int zoom = (zoomarg < 1 ? 1 : (zoomarg > NZOOM ? NZOOM : zoomarg)), ret; + if (worstcase) + ret = zoom * sys_fontspec[sys_findfont(fontsize)].fi_width; + else ret = sys_gotfonts[zoom-1][sys_findfont(fontsize)].fi_width; + return (ret < 1 ? 1 : ret); +} + +int sys_zoomfontheight(int fontsize, int zoomarg, int worstcase) +{ + int zoom = (zoomarg < 1 ? 1 : (zoomarg > NZOOM ? NZOOM : zoomarg)), ret; + if (worstcase) + ret = (zoom * sys_fontspec[sys_findfont(fontsize)].fi_height); + else ret = sys_gotfonts[zoom-1][sys_findfont(fontsize)].fi_height; + return (ret < 1 ? 1 : ret); +} + +int sys_fontwidth(int fontsize) /* old version for extern compatibility */ +{ + return (sys_zoomfontwidth(fontsize, 1, 0)); +} + +int sys_fontheight(int fontsize) +{ + return (sys_zoomfontheight(fontsize, 1, 0)); +} + +int sys_defaultfont; +#define DEFAULTFONT 10 + +static void openit(const char *dirname, const char *filename) +{ + char dirbuf[MAXPDSTRING], *nameptr; + int fd = open_via_path(dirname, filename, "", dirbuf, &nameptr, + MAXPDSTRING, 0); + if (fd >= 0) + { + close (fd); + glob_evalfile(0, gensym(nameptr), gensym(dirbuf)); + } + else + error("%s: can't open", filename); +} + +/* this is called from the gui process. The first argument is the cwd, and +succeeding args give the widths and heights of known fonts. We wait until +these are known to open files and send messages specified on the command line. +We ask the GUI to specify the "cwd" in case we don't have a local OS to get it +from; for instance we could be some kind of RT embedded system. However, to +really make this make sense we would have to implement +open(), read(), etc, calls to be served somehow from the GUI too. */ + +void glob_initfromgui(void *dummy, t_symbol *s, int argc, t_atom *argv) +{ + char *cwd = atom_getsymbolarg(0, argc, argv)->s_name; + t_namelist *nl; + unsigned int i; + int did_fontwarning = 0; + int j; + sys_oldtclversion = atom_getfloatarg(1, argc, argv); + if (argc != 2 + 3 * NZOOM * NFONT) + bug("glob_initfromgui"); + for (j = 0; j < NZOOM; j++) + for (i = 0; i < NFONT; i++) + { + int size = atom_getfloatarg(3 * (i + j * NFONT) + 2, argc, argv); + int width = atom_getfloatarg(3 * (i + j * NFONT) + 3, argc, argv); + int height = atom_getfloatarg(3 * (i + j * NFONT) + 4, argc, argv); + if (!(size && width && height)) + { + size = (j+1)*sys_fontspec[i].fi_pointsize; + width = (j+1)*sys_fontspec[i].fi_width; + height = (j+1)*sys_fontspec[i].fi_height; + if (!did_fontwarning) + { + verbose(1, "ignoring invalid font-metrics from GUI"); + did_fontwarning = 1; + } + } + sys_gotfonts[j][i].fi_pointsize = size; + sys_gotfonts[j][i].fi_width = width; + sys_gotfonts[j][i].fi_height = height; +#if 0 + fprintf(stderr, "font (%d %d %d)\n", + sys_gotfonts[j][i].fi_pointsize, sys_gotfonts[j][i].fi_width, + sys_gotfonts[j][i].fi_height); +#endif + } + /* load dynamic libraries specified with "-lib" args */ + if (sys_oktoloadfiles(0)) + { + for (nl = STUFF->st_externlist; nl; nl = nl->nl_next) + if (!sys_load_lib(0, nl->nl_string)) + post("%s: can't load library", nl->nl_string); + sys_oktoloadfiles(1); + } + /* open patches specifies with "-open" args */ + for (nl = sys_openlist; nl; nl = nl->nl_next) + openit(cwd, nl->nl_string); + namelist_free(sys_openlist); + sys_openlist = 0; + /* send messages specified with "-send" args */ + for (nl = sys_messagelist; nl; nl = nl->nl_next) + { + t_binbuf *b = binbuf_new(); + binbuf_text(b, nl->nl_string, strlen(nl->nl_string)); + binbuf_eval(b, 0, 0, 0); + binbuf_free(b); + } + namelist_free(sys_messagelist); + sys_messagelist = 0; +} + +// font char metric triples: pointsize width(pixels) height(pixels) +static int defaultfontshit[] = { + 8, 5, 11, 10, 6, 13, 12, 7, 16, 16, 10, 19, 24, 14, 29, 36, 22, 44, + 16, 10, 22, 20, 12, 26, 24, 14, 32, 32, 20, 38, 48, 28, 58, 72, 44, 88 +}; // normal & zoomed (2x) +#define NDEFAULTFONT (sizeof(defaultfontshit)/sizeof(*defaultfontshit)) + +static t_clock *sys_fakefromguiclk; +static void sys_fakefromgui(void) +{ + /* fake the GUI's message giving cwd and font sizes in case + we aren't starting the gui. */ + t_atom zz[NDEFAULTFONT+2]; + int i; + char buf[MAXPDSTRING]; +#ifdef _WIN32 + if (GetCurrentDirectory(MAXPDSTRING, buf) == 0) + strcpy(buf, "."); +#else + if (!getcwd(buf, MAXPDSTRING)) + strcpy(buf, "."); +#endif + SETSYMBOL(zz, gensym(buf)); + SETFLOAT(zz+1, 0); + for (i = 0; i < (int)NDEFAULTFONT; i++) + SETFLOAT(zz+i+2, defaultfontshit[i]); + glob_initfromgui(0, 0, 2+NDEFAULTFONT, zz); + clock_free(sys_fakefromguiclk); +} + +static void sys_afterargparse(void); + +/* this is called from main() in s_entry.c */ +int sys_main(int argc, char **argv) +{ + int i, noprefs; + char *prefsfile = ""; + sys_externalschedlib = 0; + sys_extraflags = 0; +#ifdef PD_DEBUG + fprintf(stderr, "Pd: COMPILED FOR DEBUGGING\n"); +#endif + /* use Win32 "binary" mode by default since we don't want the + * translation that Win32 does by default */ +#ifdef _WIN32 +# ifdef _MSC_VER /* MS Visual Studio */ + _set_fmode( _O_BINARY ); +# else /* MinGW */ + { + extern int _fmode; + _fmode = _O_BINARY; + } +# endif /* _MSC_VER */ +#endif /* _WIN32 */ +#ifndef _WIN32 + /* long ago Pd used setuid to promote itself to real-time priority. + Just in case anyone's installation script still makes it setuid, we + complain to stderr and lose setuid here. */ + if (getuid() != geteuid()) + { + fprintf(stderr, "warning: canceling setuid privilege\n"); + setuid(getuid()); + } +#endif /* _WIN32 */ + pd_init(); /* start the message system */ + sys_findprogdir(argv[0]); /* set sys_progname, guipath */ + for (i = noprefs = 0; i < argc; i++) /* prescan for prefs override */ + { + if (!strcmp(argv[i], "-noprefs")) + noprefs = 1; + else if (!strcmp(argv[i], "-prefsfile") && i < argc-1) + prefsfile = argv[i+1]; + } + if (!noprefs) /* load preferences before parsing args to allow ... */ + sys_loadpreferences(prefsfile, 1); /* args to override prefs */ + if (sys_argparse(argc-1, argv+1)) /* parse cmd line args */ + return (1); + sys_afterargparse(); /* post-argparse settings */ + if (sys_verbose || sys_version) fprintf(stderr, "%s compiled %s %s\n", + pd_version, pd_compiletime, pd_compiledate); + if (sys_version) /* if we were just asked our version, exit here. */ + return (0); + sys_setsignalhandlers(); + if (sys_dontstartgui) + clock_set((sys_fakefromguiclk = + clock_new(0, (t_method)sys_fakefromgui)), 0); + else if (sys_startgui(sys_libdir->s_name)) /* start the gui */ + return (1); + if (sys_hipriority) + sys_setrealtime(sys_libdir->s_name); /* set desired process priority */ + if (sys_externalschedlib) + return (sys_run_scheduler(sys_externalschedlibname, + sys_extraflagsstring)); + else if (sys_batch) + return (m_batchmain()); + else + { + /* open audio and MIDI */ + sys_reopen_midi(); + if (audio_shouldkeepopen()) + sys_reopen_audio(); + /* run scheduler until it quits */ + return (m_mainloop()); + } +} + +static char *(usagemessage[]) = { +"usage: pd [-flags] [file]...\n", +"\naudio configuration flags:\n", +"-r -- specify sample rate\n", +"-audioindev ... -- audio in devices; e.g., \"1,3\" for first and third\n", +"-audiooutdev ... -- audio out devices (same)\n", +"-audiodev ... -- specify input and output together\n", +"-audioaddindev -- add an audio input device by name\n", +"-audioaddoutdev -- add an audio output device by name\n", +"-audioadddev -- add an audio input and output device by name\n", +"-inchannels ... -- audio input channels (by device, like \"2\" or \"16,8\")\n", +"-outchannels ... -- number of audio out channels (same)\n", +"-channels ... -- specify both input and output channels\n", +"-audiobuf -- specify size of audio buffer in msec\n", +"-blocksize -- specify audio I/O block size in sample frames\n", +"-sleepgrain -- specify number of milliseconds to sleep when idle\n", +"-nodac -- suppress audio output\n", +"-noadc -- suppress audio input\n", +"-noaudio -- suppress audio input and output (-nosound is synonym) \n", +"-callback -- use callbacks if possible\n", +"-nocallback -- use polling-mode (true by default)\n", +"-listdev -- list audio and MIDI devices\n", + +#ifdef USEAPI_OSS +"-oss -- use OSS audio API\n", +#endif + +#ifdef USEAPI_ALSA +"-alsa -- use ALSA audio API\n", +"-alsaadd -- add an ALSA device name to list\n", +#endif + +#ifdef USEAPI_JACK +"-jack -- use JACK audio API\n", +"-jackname -- a name for your JACK client\n", +"-nojackconnect -- do not automatically connect pd to the JACK graph\n", +"-jackconnect -- automatically connect pd to the JACK graph [default]\n", + +#endif + +#ifdef USEAPI_PORTAUDIO +#ifdef _WIN32 +"-asio -- use ASIO audio driver (via Portaudio)\n", +"-pa -- synonym for -asio\n", +#else +"-pa -- use Portaudio API\n", +#endif +#endif + +#ifdef USEAPI_MMIO +"-mmio -- use MMIO audio API (default for Windows)\n", +#endif + +#ifdef USEAPI_AUDIOUNIT +"-audiounit -- use Apple AudioUnit API\n", +#endif + +#ifdef USEAPI_ESD +"-esd -- use Enlightenment Sound Daemon (ESD) API\n", +#endif + +" (default audio API for this platform: ", API_DEFSTRING, ")\n\n", + +"\nMIDI configuration flags:\n", +"-midiindev ... -- midi in device list; e.g., \"1,3\" for first and third\n", +"-midioutdev ... -- midi out device list, same format\n", +"-mididev ... -- specify -midioutdev and -midiindev together\n", +"-midiaddindev -- add a MIDI input device by name\n", +"-midiaddoutdev -- add a MIDI output device by name\n", +"-midiadddev -- add a MIDI input and output device by name\n", +"-nomidiin -- suppress MIDI input\n", +"-nomidiout -- suppress MIDI output\n", +"-nomidi -- suppress MIDI input and output\n", +#ifdef USEAPI_OSS +"-ossmidi -- use OSS midi API\n", +#endif +#ifdef USEAPI_ALSA +"-alsamidi -- use ALSA midi API\n", +#endif + + +"\nother flags:\n", +"-path -- add to file search path\n", +"-nostdpath -- don't search standard (\"extra\") directory\n", +"-stdpath -- search standard directory (true by default)\n", +"-helppath -- add to help file search path\n", +"-open -- open file(s) on startup\n", +"-lib -- load object library(s)\n", +"-font-size -- specify default font size in points\n", +"-font-face -- specify default font\n", +"-font-weight -- specify default font weight (normal or bold)\n", +"-verbose -- extra printout on startup and when searching for files\n", +"-noverbose -- no extra printout\n", +"-version -- don't run Pd; just print out which version it is \n", +"-d -- specify debug level\n", +"-loadbang -- do not suppress all loadbangs (true by default)\n", +"-noloadbang -- suppress all loadbangs\n", +"-stderr -- send printout to standard error instead of GUI\n", +"-nostderr -- send printout to GUI (true by default)\n", +"-gui -- start GUI (true by default)\n", +"-nogui -- suppress starting the GUI\n", +"-guiport -- connect to pre-existing GUI over port \n", +"-guicmd \"cmd...\" -- start alternatve GUI program (e.g., remote via ssh)\n", +"-send \"msg...\" -- send a message at startup, after patches are loaded\n", +"-prefs -- load preferences on startup (true by default)\n", +"-noprefs -- suppress loading preferences on startup\n", +"-prefsfile -- load preferences from a file\n", +#ifdef HAVE_UNISTD_H +"-rt or -realtime -- use real-time priority\n", +"-nrt -- don't use real-time priority\n", +#endif +"-sleep -- sleep when idle, don't spin (true by default)\n", +"-nosleep -- spin, don't sleep (may lower latency on multi-CPUs)\n", +"-schedlib -- plug in external scheduler\n", +"-extraflags -- string argument to send schedlib\n", +"-batch -- run off-line as a batch process\n", +"-nobatch -- run interactively (true by default)\n", +"-autopatch -- enable auto-patching to new objects (true by default)\n", +"-noautopatch -- defeat auto-patching\n", +"-compatibility -- set back-compatibility to version \n", +}; + +static void sys_parsedevlist(int *np, int *vecp, int max, char *str) +{ + int n = 0; + while (n < max) + { + if (!*str) break; + else + { + char *endp; + vecp[n] = (int)strtol(str, &endp, 10); + if (endp == str) + break; + n++; + if ('\0' == *endp) + break; + str = endp + 1; + } + } + *np = n; +} + +static int sys_getmultidevchannels(int n, int *devlist) +{ + int sum = 0; + if (n<0)return(-1); + if (n==0)return 0; + while(n--)sum+=*devlist++; + return sum; +} + + + /* this routine tries to figure out where to find the auxiliary files + Pd will need to run. This is either done by looking at the command line + invocation for Pd, or if that fails, by consulting the variable + INSTALL_PREFIX. In MSW, we don't try to use INSTALL_PREFIX. */ +void sys_findprogdir(char *progname) +{ + char sbuf[MAXPDSTRING], sbuf2[MAXPDSTRING], *sp; + char *lastslash; +#ifndef _WIN32 + struct stat statbuf; +#endif /* NOT _WIN32 */ + + /* find out by what string Pd was invoked; put answer in "sbuf". */ +#ifdef _WIN32 + GetModuleFileName(NULL, sbuf2, sizeof(sbuf2)); + sbuf2[MAXPDSTRING-1] = 0; + sys_unbashfilename(sbuf2, sbuf); +#else + strncpy(sbuf, progname, MAXPDSTRING); + sbuf[MAXPDSTRING-1] = 0; +#endif /* _WIN32 */ + lastslash = strrchr(sbuf, '/'); + if (lastslash) + { + /* bash last slash to zero so that sbuf is directory pd was in, + e.g., ~/pd/bin */ + *lastslash = 0; + /* go back to the parent from there, e.g., ~/pd */ + lastslash = strrchr(sbuf, '/'); + if (lastslash) + { + strncpy(sbuf2, sbuf, lastslash-sbuf); + sbuf2[lastslash-sbuf] = 0; + } + else strcpy(sbuf2, ".."); + } + else + { + /* no slashes found. Try INSTALL_PREFIX. */ +#ifdef INSTALL_PREFIX + strcpy(sbuf2, INSTALL_PREFIX); +#else + strcpy(sbuf2, "."); +#endif + } + /* now we believe sbuf2 holds the parent directory of the directory + pd was found in. We now want to infer the "lib" directory and the + "gui" directory. In "simple" unix installations, the layout is + .../bin/pd + .../bin/pd-watchdog (etc) + .../bin/pd-gui.tcl + .../doc + and in "complicated" unix installations, it's: + .../bin/pd + .../lib/pd/bin/pd-watchdog + .../lib/pd/bin/pd-gui.tcl + .../lib/pd/doc + To decide which, we stat .../lib/pd; if that exists, we assume it's + the complicated layout. In MSW, it's the "simple" layout, but + "wish" is found in bin: + .../bin/pd + .../bin/wish80.exe + .../doc + */ +#ifdef _WIN32 + sys_libdir = gensym(sbuf2); +#else + strncpy(sbuf, sbuf2, MAXPDSTRING-30); + sbuf[MAXPDSTRING-30] = 0; + strcat(sbuf, "/lib/pd"); + if (stat(sbuf, &statbuf) >= 0) + { + /* complicated layout: lib dir is the one we just stat-ed above */ + sys_libdir = gensym(sbuf); + } + else + { + /* simple layout: lib dir is the parent */ + sys_libdir = gensym(sbuf2); + } +#endif +} + +#ifdef _WIN32 +static int sys_mmio = 1; +#else +static int sys_mmio = 0; +#endif + +int sys_argparse(int argc, char **argv) +{ + char sbuf[MAXPDSTRING]; + int i; + while ((argc > 0) && **argv == '-') + { + if (!strcmp(*argv, "-r") && argc > 1 && + sscanf(argv[1], "%d", &sys_main_srate) >= 1) + { + argc -= 2; + argv += 2; + } + else if (!strcmp(*argv, "-inchannels")) + { + if (argc < 2) + goto usage; + + sys_parsedevlist(&sys_nchin, + sys_chinlist, MAXAUDIOINDEV, argv[1]); + + if (!sys_nchin) + goto usage; + + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-outchannels")) + { + if (argc < 2) + goto usage; + + sys_parsedevlist(&sys_nchout, sys_choutlist, + MAXAUDIOOUTDEV, argv[1]); + + if (!sys_nchout) + goto usage; + + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-channels")) + { + if (argc < 2) + goto usage; + + sys_parsedevlist(&sys_nchin, sys_chinlist,MAXAUDIOINDEV, + argv[1]); + sys_parsedevlist(&sys_nchout, sys_choutlist,MAXAUDIOOUTDEV, + argv[1]); + + if (!sys_nchout) + goto usage; + + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-soundbuf") || (!strcmp(*argv, "-audiobuf"))) + { + if (argc < 2) + goto usage; + + sys_main_advance = atoi(argv[1]); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-callback")) + { + sys_main_callback = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-nocallback")) + { + sys_main_callback = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-blocksize")) + { + sys_main_blocksize = atoi(argv[1]); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-sleepgrain")) + { + if (argc < 2) + goto usage; + + sys_sleepgrain = 1000 * atof(argv[1]); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-nodac")) + { + sys_nsoundout=0; + sys_nchout = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-noadc")) + { + sys_nsoundin=0; + sys_nchin = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-nosound") || !strcmp(*argv, "-noaudio")) + { + sys_nsoundin=sys_nsoundout = 0; + sys_nchin = sys_nchout = 0; + argc--; argv++; + } +#ifdef USEAPI_OSS + else if (!strcmp(*argv, "-oss")) + { + sys_set_audio_api(API_OSS); + argc--; argv++; + } + else if (!strcmp(*argv, "-ossmidi")) + { + sys_set_midi_api(API_OSS); + argc--; argv++; + } +#else + else if (!strcmp(*argv, "-oss") || !strcmp(*argv, "-ossmidi")) + { + fprintf(stderr, "Pd compiled without OSS-support, ignoring '%s' flag\n", *argv); + argc--; argv++; + } +#endif +#ifdef USEAPI_ALSA + else if (!strcmp(*argv, "-alsa")) + { + sys_set_audio_api(API_ALSA); + argc--; argv++; + } + else if (!strcmp(*argv, "-alsaadd")) + { + if (argc < 2) + goto usage; + + alsa_adddev(argv[1]); + argc -= 2; argv +=2; + } + else if (!strcmp(*argv, "-alsamidi")) + { + sys_set_midi_api(API_ALSA); + argc--; argv++; + } +#else + else if (!strcmp(*argv, "-alsa") || !strcmp(*argv, "-alsamidi")) + { + fprintf(stderr, "Pd compiled without ALSA-support, ignoring '%s' flag\n", *argv); + argc--; argv++; + } + else if (!strcmp(*argv, "-alsaadd")) + { + if (argc < 2) + goto usage; + fprintf(stderr, "Pd compiled without ALSA-support, ignoring '%s' flag\n", *argv); + argc -= 2; argv +=2; + } +#endif +#ifdef USEAPI_JACK + else if (!strcmp(*argv, "-jack")) + { + sys_set_audio_api(API_JACK); + argc--; argv++; + } + else if (!strcmp(*argv, "-nojackconnect")) + { + jack_autoconnect(0); + argc--; argv++; + } + else if (!strcmp(*argv, "-jackconnect")) + { + jack_autoconnect(1); + argc--; argv++; + } + else if (!strcmp(*argv, "-jackname")) + { + if (argc < 2) + goto usage; + + sys_set_audio_api(API_JACK), jack_client_name(argv[1]); + argc -= 2; argv +=2; + + } +#else + else if (!strcmp(*argv, "-jack") || !strcmp(*argv, "-nojackconnect") + || !strcmp(*argv, "-jackconnect")) + { + fprintf(stderr, "Pd compiled without JACK-support, ignoring '%s' flag\n", *argv); + argc--; argv++; + } + else if (!strcmp(*argv, "-jackname")) + { + if (argc < 2) + goto usage; + fprintf(stderr, "Pd compiled without JACK-support, ignoring '%s' flag\n", *argv); + argc -= 2; argv +=2; + } +#endif +#ifdef USEAPI_PORTAUDIO + else if (!strcmp(*argv, "-pa") || !strcmp(*argv, "-portaudio") + || !strcmp(*argv, "-asio") + ) + { + sys_set_audio_api(API_PORTAUDIO); + sys_mmio = 0; + argc--; argv++; + } +#else + else if (!strcmp(*argv, "-pa") || !strcmp(*argv, "-portaudio") + || !strcmp(*argv, "-asio") + ) + { + fprintf(stderr, "Pd compiled without PortAudio-support, ignoring '%s' flag\n", *argv); + argc--; argv++; + } +#endif +#ifdef USEAPI_MMIO + else if (!strcmp(*argv, "-mmio")) + { + sys_set_audio_api(API_MMIO); + sys_mmio = 1; + argc--; argv++; + } +#else + else if (!strcmp(*argv, "-mmio")) + { + fprintf(stderr, "Pd compiled without MMIO-support, ignoring '%s' flag\n", *argv); + argc--; argv++; + } +#endif +#ifdef USEAPI_AUDIOUNIT + else if (!strcmp(*argv, "-audiounit")) + { + sys_set_audio_api(API_AUDIOUNIT); + argc--; argv++; + } +#endif +#ifdef USEAPI_ESD + else if (!strcmp(*argv, "-esd")) + { + sys_set_audio_api(API_ESD); + argc--; argv++; + } +#endif + else if (!strcmp(*argv, "-nomidiin")) + { + sys_nmidiin = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-nomidiout")) + { + sys_nmidiout = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-nomidi")) + { + sys_nmidiin = sys_nmidiout = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-midiindev")) + { + if (argc < 2) + goto usage; + + sys_parsedevlist(&sys_nmidiin, sys_midiindevlist, MAXMIDIINDEV, + argv[1]); + if (!sys_nmidiin) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-midioutdev")) + { + if (argc < 2) + goto usage; + + sys_parsedevlist(&sys_nmidiout, sys_midioutdevlist, MAXMIDIOUTDEV, + argv[1]); + if (!sys_nmidiout) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-mididev")) + { + if (argc < 2) + goto usage; + + sys_parsedevlist(&sys_nmidiin, sys_midiindevlist, MAXMIDIINDEV, + argv[1]); + sys_parsedevlist(&sys_nmidiout, sys_midioutdevlist, MAXMIDIOUTDEV, + argv[1]); + if (!sys_nmidiout) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-midiaddindev")) + { + if (argc < 2) + goto usage; + + if (sys_nmidiin < 0) + sys_nmidiin = 0; + if (sys_nmidiin < MAXMIDIINDEV) + { + int devn = sys_mididevnametonumber(0, argv[1]); + if (devn < 0) + fprintf(stderr, "Couldn't find MIDI input device: %s\n", + argv[1]); + else sys_midiindevlist[sys_nmidiin++] = devn + 1; + } + else fprintf(stderr, "number of MIDI devices limited to %d\n", + MAXMIDIINDEV); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-midiaddoutdev")) + { + if (argc < 2) + goto usage; + + if (sys_nmidiout < 0) + sys_nmidiout = 0; + if (sys_nmidiout < MAXMIDIINDEV) + { + int devn = sys_mididevnametonumber(1, argv[1]); + if (devn < 0) + fprintf(stderr, "Couldn't find MIDI output device: %s\n", + argv[1]); + else sys_midioutdevlist[sys_nmidiout++] = devn + 1; + } + else fprintf(stderr, "number of MIDI devices limited to %d\n", + MAXMIDIINDEV); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-midiadddev")) + { + if (argc < 2) + goto usage; + + if (sys_nmidiin < 0) + sys_nmidiin = 0; + if (sys_nmidiout < 0) + sys_nmidiout = 0; + if (sys_nmidiin < MAXMIDIINDEV && sys_nmidiout < MAXMIDIINDEV) + { + int devn = sys_mididevnametonumber(1, argv[1]); + if (devn < 0) + fprintf(stderr, "Couldn't find MIDI output device: %s\n", + argv[1]); + else sys_midioutdevlist[sys_nmidiin++] = devn + 1; + devn = sys_mididevnametonumber(1, argv[1]); + if (devn < 0) + fprintf(stderr, "Couldn't find MIDI output device: %s\n", + argv[1]); + else sys_midioutdevlist[sys_nmidiout++] = devn + 1; + } + else fprintf(stderr, "number of MIDI devices limited to %d", + MAXMIDIINDEV); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-path")) + { + if (argc < 2) + goto usage; + STUFF->st_searchpath = + namelist_append_files(STUFF->st_searchpath, argv[1]); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-nostdpath")) + { + sys_usestdpath = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-stdpath")) + { + sys_usestdpath = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-helppath")) + { + if (argc < 2) + goto usage; + STUFF->st_helppath = + namelist_append_files(STUFF->st_helppath, argv[1]); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-open")) + { + if (argc < 2) + goto usage; + + sys_openlist = namelist_append_files(sys_openlist, argv[1]); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-lib")) + { + if (argc < 2) + goto usage; + + STUFF->st_externlist = + namelist_append_files(STUFF->st_externlist, argv[1]); + argc -= 2; argv += 2; + } + else if ((!strcmp(*argv, "-font-size") || !strcmp(*argv, "-font"))) + { + if (argc < 2) + goto usage; + + sys_defaultfont = sys_nearestfontsize(atoi(argv[1])); + argc -= 2; + argv += 2; + } + else if ((!strcmp(*argv, "-font-face") || !strcmp(*argv, "-typeface"))) + { + if (argc < 2) + goto usage; + + strncpy(sys_font,*(argv+1),sizeof(sys_font)-1); + sys_font[sizeof(sys_font)-1] = 0; + argc -= 2; + argv += 2; + } + else if (!strcmp(*argv, "-font-weight")) + { + if (argc < 2) + goto usage; + + strncpy(sys_fontweight,*(argv+1),sizeof(sys_fontweight)-1); + sys_fontweight[sizeof(sys_fontweight)-1] = 0; + argc -= 2; + argv += 2; + } + else if (!strcmp(*argv, "-verbose")) + { + sys_verbose++; + argc--; argv++; + } + else if (!strcmp(*argv, "-noverbose")) + { + sys_verbose=0; + argc--; argv++; + } + else if (!strcmp(*argv, "-version")) + { + sys_version = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-d") && argc > 1 && + sscanf(argv[1], "%d", &sys_debuglevel) >= 1) + { + argc -= 2; + argv += 2; + } + else if (!strcmp(*argv, "-loadbang")) + { + sys_noloadbang = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-noloadbang")) + { + sys_noloadbang = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-gui")) + { + sys_dontstartgui = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-nogui")) + { + sys_dontstartgui = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-guiport") && argc > 1 && + sscanf(argv[1], "%d", &sys_guisetportnumber) >= 1) + { + argc -= 2; + argv += 2; + } + else if (!strcmp(*argv, "-nostderr")) + { + sys_printtostderr = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-stderr")) + { + sys_printtostderr = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-guicmd")) + { + if (argc < 2) + goto usage; + + sys_guicmd = argv[1]; + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-send")) + { + if (argc < 2) + goto usage; + + sys_messagelist = namelist_append(sys_messagelist, argv[1], 1); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-listdev")) + { + sys_listplease = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-schedlib")) + { + if (argc < 2) + goto usage; + + sys_externalschedlib = 1; + strncpy(sys_externalschedlibname, argv[1], + sizeof(sys_externalschedlibname) - 1); +#ifndef __APPLE__ + /* no real audio please, unless overwritten by later args. + This is to circumvent a problem running pd~ subprocesses + with -nogui; they would open an audio device before pdsched.c + could set the API ito nothing. For some reason though, on + MACOSX this causes Pd to switch to JACK so we just give up + and suppress the workaround there. */ + sys_set_audio_api(0); +#endif + argv += 2; + argc -= 2; + } + else if (!strcmp(*argv, "-extraflags")) + { + if (argc < 2) + goto usage; + + sys_extraflags = 1; + strncpy(sys_extraflagsstring, argv[1], + sizeof(sys_extraflagsstring) - 1); + argv += 2; + argc -= 2; + } + else if (!strcmp(*argv, "-batch")) + { + sys_batch = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-nobatch")) + { + sys_batch = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-autopatch")) + { + sys_noautopatch = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-noautopatch")) + { + sys_noautopatch = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-compatibility")) + { + float f; + if (argc < 2) + goto usage; + + if (sscanf(argv[1], "%f", &f) < 1) + goto usage; + pd_compatibilitylevel = 0.5 + 100. * f; /* e.g., 2.44 --> 244 */ + argv += 2; + argc -= 2; + } +#ifdef HAVE_UNISTD_H + else if (!strcmp(*argv, "-rt") || !strcmp(*argv, "-realtime")) + { + sys_hipriority = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-nrt") || !strcmp(*argv, "-nort") || !strcmp(*argv, "-norealtime")) + { + sys_hipriority = 0; + argc--; argv++; + } +#else + else if (!strcmp(*argv, "-rt") || !strcmp(*argv, "-realtime") + || !strcmp(*argv, "-nrt") || !strcmp(*argv, "-nort") + || !strcmp(*argv, "-norealtime")) + { + fprintf(stderr, "Pd compiled without realtime priority-support, ignoring '%s' flag\n", *argv); + argc--; argv++; + } +#endif + else if (!strcmp(*argv, "-sleep")) + { + sys_nosleep = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-nosleep")) + { + sys_nosleep = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-soundindev") || + !strcmp(*argv, "-audioindev")) + { + sys_parsedevlist(&sys_nsoundin, sys_soundindevlist, + MAXAUDIOINDEV, argv[1]); + if (!sys_nsoundin) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-soundoutdev") || + !strcmp(*argv, "-audiooutdev")) + { + if (argc < 2) + goto usage; + + sys_parsedevlist(&sys_nsoundout, sys_soundoutdevlist, + MAXAUDIOOUTDEV, argv[1]); + if (!sys_nsoundout) + goto usage; + argc -= 2; argv += 2; + } + else if ((!strcmp(*argv, "-sounddev") || !strcmp(*argv, "-audiodev"))) + { + if (argc < 2) + goto usage; + + sys_parsedevlist(&sys_nsoundin, sys_soundindevlist, + MAXAUDIOINDEV, argv[1]); + sys_parsedevlist(&sys_nsoundout, sys_soundoutdevlist, + MAXAUDIOOUTDEV, argv[1]); + if (!sys_nsoundout) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-audioaddindev")) + { + if (argc < 2) + goto usage; + + if (sys_nsoundin < 0) + sys_nsoundin = 0; + if (sys_nsoundin < MAXAUDIOINDEV) + { + int devn = sys_audiodevnametonumber(0, argv[1]); + if (devn < 0) + fprintf(stderr, "Couldn't find audio input device: %s\n", + argv[1]); + else sys_soundindevlist[sys_nsoundin++] = devn + 1; + } + else fprintf(stderr, "number of audio devices limited to %d\n", + MAXAUDIOINDEV); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-audioaddoutdev")) + { + if (argc < 2) + goto usage; + + if (sys_nsoundout < 0) + sys_nsoundout = 0; + if (sys_nsoundout < MAXAUDIOINDEV) + { + int devn = sys_audiodevnametonumber(1, argv[1]); + if (devn < 0) + fprintf(stderr, "Couldn't find audio output device: %s\n", + argv[1]); + else sys_soundoutdevlist[sys_nsoundout++] = devn + 1; + } + else fprintf(stderr, "number of audio devices limited to %d\n", + MAXAUDIOINDEV); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-audioadddev")) + { + if (argc < 2) + goto usage; + + if (sys_nsoundin < 0) + sys_nsoundin = 0; + if (sys_nsoundout < 0) + sys_nsoundout = 0; + if (sys_nsoundin < MAXAUDIOINDEV && sys_nsoundout < MAXAUDIOINDEV) + { + int devn = sys_audiodevnametonumber(0, argv[1]); + if (devn < 0) + fprintf(stderr, "Couldn't find audio input device: %s\n", + argv[1]); + else sys_soundindevlist[sys_nsoundin++] = devn + 1; + devn = sys_audiodevnametonumber(1, argv[1]); + if (devn < 0) + fprintf(stderr, "Couldn't find audio output device: %s\n", + argv[1]); + else sys_soundoutdevlist[sys_nsoundout++] = devn + 1; + } + else fprintf(stderr, "number of audio devices limited to %d", + MAXAUDIOINDEV); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-noprefs")) /* did this earlier */ + argc--, argv++; + else if (!strcmp(*argv, "-prefsfile") && argc > 1) /* this too */ + argc -= 2, argv +=2; + else + { + unsigned int i; + usage: + for (i = 0; i < sizeof(usagemessage)/sizeof(*usagemessage); i++) + fprintf(stderr, "%s", usagemessage[i]); + return (1); + } + } + if (sys_batch) + sys_dontstartgui = 1; + if (sys_dontstartgui) + sys_printtostderr = 1; +#ifdef _WIN32 + if (sys_printtostderr) + /* we need to tell Windows to output UTF-8 */ + SetConsoleOutputCP(CP_UTF8); +#endif + if (!sys_defaultfont) + sys_defaultfont = DEFAULTFONT; + for (; argc > 0; argc--, argv++) + sys_openlist = namelist_append_files(sys_openlist, *argv); + + + return (0); +} + +int sys_getblksize(void) +{ + return (DEFDACBLKSIZE); +} + + /* stuff to do, once, after calling sys_argparse() -- which may itself + be called more than once (first from "settings, second from .pdrc, then + from command-line arguments */ +static void sys_afterargparse(void) +{ + char sbuf[MAXPDSTRING]; + int i; + int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV]; + int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV]; + int nchindev, nchoutdev, rate, advance, callback, blocksize; + int nmidiindev = 0, midiindev[MAXMIDIINDEV]; + int nmidioutdev = 0, midioutdev[MAXMIDIOUTDEV]; + /* add "extra" library to path */ + strncpy(sbuf, sys_libdir->s_name, MAXPDSTRING-30); + sbuf[MAXPDSTRING-30] = 0; + strcat(sbuf, "/extra"); + sys_setextrapath(sbuf); + /* add "doc/5.reference" library to helppath */ + strncpy(sbuf, sys_libdir->s_name, MAXPDSTRING-30); + sbuf[MAXPDSTRING-30] = 0; + strcat(sbuf, "/doc/5.reference"); + STUFF->st_staticpath = namelist_append_files(STUFF->st_staticpath, sbuf); + /* correct to make audio and MIDI device lists zero based. On + MMIO, however, "1" really means the second device (the first one + is "mapper" which is was not included when the command args were + set up, so we leave it that way for compatibility. */ + if (!sys_mmio) + { + for (i = 0; i < sys_nsoundin; i++) + sys_soundindevlist[i]--; + for (i = 0; i < sys_nsoundout; i++) + sys_soundoutdevlist[i]--; + } + for (i = 0; i < sys_nmidiin; i++) + sys_midiindevlist[i]--; + for (i = 0; i < sys_nmidiout; i++) + sys_midioutdevlist[i]--; + if (sys_listplease) + sys_listdevs(); + + /* get the current audio parameters. These are set + by the preferences mechanism (sys_loadpreferences()) or + else are the default. Overwrite them with any results + of argument parsing, and store them again. */ + sys_get_audio_params(&naudioindev, audioindev, chindev, + &naudiooutdev, audiooutdev, choutdev, &rate, &advance, + &callback, &blocksize); + if (sys_nchin >= 0) + { + nchindev = sys_nchin; + for (i = 0; i < nchindev; i++) + chindev[i] = sys_chinlist[i]; + } + else nchindev = naudioindev; + if (sys_nsoundin >= 0) + { + naudioindev = sys_nsoundin; + for (i = 0; i < naudioindev; i++) + audioindev[i] = sys_soundindevlist[i]; + } + + if (sys_nchout >= 0) + { + nchoutdev = sys_nchout; + for (i = 0; i < nchoutdev; i++) + choutdev[i] = sys_choutlist[i]; + } + else nchoutdev = naudiooutdev; + if (sys_nsoundout >= 0) + { + naudiooutdev = sys_nsoundout; + for (i = 0; i < naudiooutdev; i++) + audiooutdev[i] = sys_soundoutdevlist[i]; + } + sys_get_midi_params(&nmidiindev, midiindev, &nmidioutdev, midioutdev); + if (sys_nmidiin >= 0) + { + nmidiindev = sys_nmidiin; + for (i = 0; i < nmidiindev; i++) + midiindev[i] = sys_midiindevlist[i]; + } + if (sys_nmidiout >= 0) + { + nmidioutdev = sys_nmidiout; + for (i = 0; i < nmidioutdev; i++) + midioutdev[i] = sys_midioutdevlist[i]; + } + if (sys_main_advance) + advance = sys_main_advance; + if (sys_main_srate) + rate = sys_main_srate; + if (sys_main_callback) + callback = sys_main_callback; + if (sys_main_blocksize) + blocksize = sys_main_blocksize; + sys_set_audio_settings(naudioindev, audioindev, nchindev, chindev, + naudiooutdev, audiooutdev, nchoutdev, choutdev, rate, advance, + callback, blocksize); + sys_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev, 0); +} + +static void sys_addreferencepath(void) +{ + char sbuf[MAXPDSTRING]; +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_midi.c b/ports/camomile/source/LibPd/pure-data/src/s_midi.c new file mode 100644 index 00000000..fc7b86c0 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_midi.c @@ -0,0 +1,919 @@ +/* Copyright (c) 1997-1999 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* Clock functions (which should move, but where?) and MIDI queueing */ + +#include "m_pd.h" +#include "s_stuff.h" +#include "m_imp.h" +#ifdef HAVE_UNISTD_H +#include +#include +#ifdef HAVE_BSTRING_H +#include +#endif +#endif +#ifdef _WIN32 +#include +#include +#include +#include +#endif +#include +#include +#include + +/* channel voice messages */ /* dec, # */ +#define MIDI_NOTEOFF 0x80 /* 128, 2 */ +#define MIDI_NOTEON 0x90 /* 144, 2 */ +#define MIDI_POLYAFTERTOUCH 0xa0 /* 160, 2 (aka key pressure) */ +#define MIDI_CONTROLCHANGE 0xb0 /* 176, 2 */ +#define MIDI_PROGRAMCHANGE 0xc0 /* 192, 1 */ +#define MIDI_AFTERTOUCH 0xd0 /* 208, 1 (aka channel pressure) */ +#define MIDI_PITCHBEND 0xe0 /* 224, 2 */ + +/* system common messages */ +#define MIDI_SYSEX 0xf0 /* 240, N (until MIDI_SYSEXEND) */ +#define MIDI_TIMECODE 0xf1 /* 241, 1 */ +#define MIDI_SONGPOS 0xf2 /* 242, 2 */ +#define MIDI_SONGSELECT 0xf3 /* 243, 1 */ +#define MIDI_RESERVED1 0xf4 /* 244, ? */ +#define MIDI_RESERVED2 0xf5 /* 245, ? */ +#define MIDI_TUNEREQUEST 0xf6 /* 246, 0 */ +#define MIDI_SYSEXEND 0xf7 /* 247, 0 */ + +/* realtime messages */ +#define MIDI_CLOCK 0xf8 /* 248, 0 */ +// MIDI_RESERVED3 0xf9 /* 249, ? */ +#define MIDI_START 0xfa /* 250, 0 */ +#define MIDI_CONTINUE 0xfb /* 251, 0 */ +#define MIDI_STOP 0xfc /* 252, 0 */ +// MIDI_RESERVED4 0xfd /* 253, ? */ +#define MIDI_ACTIVESENSING 0xfe /* 254, 0 */ +#define MIDI_SYSTEMRESET 0xff /* 255, 0 */ + +typedef struct _midiqelem +{ + double q_time; + int q_portno; + unsigned char q_onebyte; + unsigned char q_byte1; + unsigned char q_byte2; + unsigned char q_byte3; +} t_midiqelem; + +#define MIDIQSIZE 1024 + +t_midiqelem midi_outqueue[MIDIQSIZE]; +int midi_outhead, midi_outtail; +t_midiqelem midi_inqueue[MIDIQSIZE]; +int midi_inhead, midi_intail; +static double sys_midiinittime; +#define API_DEFAULTMIDI 0 + +#if (defined USEAPI_ALSA) && (defined USEAPI_MIDIDUMMY) + /* if the only available MIDI-backend is ALSA, choose that */ +# define FORCEAPI_ALSA +#endif + + +int sys_midiapi = +#ifdef FORCEAPI_ALSA + API_ALSA +#else + API_DEFAULTMIDI +#endif + ; + + /* this is our current estimate for at what "system" real time the + current logical time's output should occur. */ +static double sys_dactimeminusrealtime; + /* same for input, should be schduler advance earlier. */ +static double sys_adctimeminusrealtime; + +static double sys_newdactimeminusrealtime = -1e20; +static double sys_newadctimeminusrealtime = -1e20; +static double sys_whenupdate; + +void sys_initmidiqueue(void) +{ + sys_midiinittime = clock_getlogicaltime(); + sys_dactimeminusrealtime = sys_adctimeminusrealtime = 0; +} + + /* this is called from the OS dependent code from time to time when we + think we know the delay (outbuftime) in seconds, at which the last-output + audio sample will go out the door. */ +void sys_setmiditimediff(double inbuftime, double outbuftime) +{ + double dactimeminusrealtime = + .001 * clock_gettimesince(sys_midiinittime) + - outbuftime - sys_getrealtime(); + double adctimeminusrealtime = + .001 * clock_gettimesince(sys_midiinittime) + + inbuftime - sys_getrealtime(); + if (dactimeminusrealtime > sys_newdactimeminusrealtime) + sys_newdactimeminusrealtime = dactimeminusrealtime; + if (adctimeminusrealtime > sys_newadctimeminusrealtime) + sys_newadctimeminusrealtime = adctimeminusrealtime; + if (sys_getrealtime() > sys_whenupdate) + { + sys_dactimeminusrealtime = sys_newdactimeminusrealtime; + sys_adctimeminusrealtime = sys_newadctimeminusrealtime; + sys_newdactimeminusrealtime = -1e20; + sys_newadctimeminusrealtime = -1e20; + sys_whenupdate = sys_getrealtime() + 1; + } +} + + /* return the logical time of the DAC sample we believe is currently + going out, based on how much "system time" has elapsed since the + last time sys_setmiditimediff got called. */ +static double sys_getmidioutrealtime(void) +{ + return (sys_getrealtime() + sys_dactimeminusrealtime); +} + +static double sys_getmidiinrealtime(void) +{ + return (sys_getrealtime() + sys_adctimeminusrealtime); +} + +static void sys_putnext(void) +{ + int portno = midi_outqueue[midi_outtail].q_portno; +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + { + if (midi_outqueue[midi_outtail].q_onebyte) + sys_alsa_putmidibyte(portno, midi_outqueue[midi_outtail].q_byte1); + else sys_alsa_putmidimess(portno, midi_outqueue[midi_outtail].q_byte1, + midi_outqueue[midi_outtail].q_byte2, + midi_outqueue[midi_outtail].q_byte3); + } + else +#endif /* ALSA */ + { + if (midi_outqueue[midi_outtail].q_onebyte) + sys_putmidibyte(portno, midi_outqueue[midi_outtail].q_byte1); + else sys_putmidimess(portno, midi_outqueue[midi_outtail].q_byte1, + midi_outqueue[midi_outtail].q_byte2, + midi_outqueue[midi_outtail].q_byte3); + } + midi_outtail = (midi_outtail + 1 == MIDIQSIZE ? 0 : midi_outtail + 1); +} + +/* #define TEST_DEJITTER */ + +void sys_pollmidioutqueue(void) +{ +#ifdef TEST_DEJITTER + static int db = 0; +#endif + double midirealtime = sys_getmidioutrealtime(); +#ifdef TEST_DEJITTER + if (midi_outhead == midi_outtail) + db = 0; +#endif + while (midi_outhead != midi_outtail) + { +#ifdef TEST_DEJITTER + if (!db) + { + post("out: del %f, midiRT %f logicaltime %f, RT %f dacminusRT %f", + (midi_outqueue[midi_outtail].q_time - midirealtime), + midirealtime, .001 * clock_gettimesince(sys_midiinittime), + sys_getrealtime(), sys_dactimeminusrealtime); + db = 1; + } +#endif + if (midi_outqueue[midi_outtail].q_time <= midirealtime) + sys_putnext(); + else break; + } +} + +/* ------------------------- MIDI output queue handling ------------------ */ + +static void sys_queuemidimess(int portno, int onebyte, int a, int b, int c) +{ + t_midiqelem *midiqelem; + int newhead = midi_outhead +1; + if (newhead == MIDIQSIZE) + newhead = 0; + /* if FIFO is full flush an element to make room */ + if (newhead == midi_outtail) + sys_putnext(); + midi_outqueue[midi_outhead].q_portno = portno; + midi_outqueue[midi_outhead].q_onebyte = onebyte; + midi_outqueue[midi_outhead].q_byte1 = a; + midi_outqueue[midi_outhead].q_byte2 = b; + midi_outqueue[midi_outhead].q_byte3 = c; + midi_outqueue[midi_outhead].q_time = + .001 * clock_gettimesince(sys_midiinittime); + midi_outhead = newhead; + sys_pollmidioutqueue(); +} + +void outmidi_noteon(int portno, int channel, int pitch, int velo) +{ + if (pitch < 0) pitch = 0; + else if (pitch > 127) pitch = 127; + if (velo < 0) velo = 0; + else if (velo > 127) velo = 127; + sys_queuemidimess(portno, 0, MIDI_NOTEON + (channel & 0xf), pitch, velo); +} + +void outmidi_controlchange(int portno, int channel, int ctl, int value) +{ + if (ctl < 0) ctl = 0; + else if (ctl > 127) ctl = 127; + if (value < 0) value = 0; + else if (value > 127) value = 127; + sys_queuemidimess(portno, 0, MIDI_CONTROLCHANGE + (channel & 0xf), + ctl, value); +} + +void outmidi_programchange(int portno, int channel, int value) +{ + if (value < 0) value = 0; + else if (value > 127) value = 127; + sys_queuemidimess(portno, 0, + MIDI_PROGRAMCHANGE + (channel & 0xf), value, 0); +} + +void outmidi_pitchbend(int portno, int channel, int value) +{ + if (value < 0) value = 0; + else if (value > 16383) value = 16383; + sys_queuemidimess(portno, 0, MIDI_PITCHBEND + (channel & 0xf), + (value & 127), ((value>>7) & 127)); +} + +void outmidi_aftertouch(int portno, int channel, int value) +{ + if (value < 0) value = 0; + else if (value > 127) value = 127; + sys_queuemidimess(portno, 0, MIDI_AFTERTOUCH + (channel & 0xf), value, 0); +} + +void outmidi_polyaftertouch(int portno, int channel, int pitch, int value) +{ + if (pitch < 0) pitch = 0; + else if (pitch > 127) pitch = 127; + if (value < 0) value = 0; + else if (value > 127) value = 127; + sys_queuemidimess(portno, 0, MIDI_POLYAFTERTOUCH + (channel & 0xf), + pitch, value); +} + +void outmidi_byte(int portno, int value) +{ +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + { + sys_alsa_putmidibyte(portno, value); + } + else +#endif + { + sys_putmidibyte(portno, value); + } +} + +/* ------------------------- MIDI input queue handling ------------------ */ +typedef struct midiparser +{ + int mp_status; /* current status byte */ + int mp_gotbyte1; /* do we have a second data byte? */ + int mp_byte1; /* second data byte */ +} t_midiparser; + + /* functions in x_midi.c */ +void inmidi_realtimein(int portno, int cmd); +void inmidi_byte(int portno, int byte); +void inmidi_sysex(int portno, int byte); +void inmidi_noteon(int portno, int channel, int pitch, int velo); +void inmidi_controlchange(int portno, int channel, int ctlnumber, int value); +void inmidi_programchange(int portno, int channel, int value); +void inmidi_pitchbend(int portno, int channel, int value); +void inmidi_aftertouch(int portno, int channel, int value); +void inmidi_polyaftertouch(int portno, int channel, int pitch, int value); + +static void sys_dispatchnextmidiin(void) +{ + static t_midiparser parser[MAXMIDIINDEV], *parserp; + int portno = midi_inqueue[midi_intail].q_portno, + byte = midi_inqueue[midi_intail].q_byte1; + if (!midi_inqueue[midi_intail].q_onebyte) + bug("sys_dispatchnextmidiin"); + if (portno < 0 || portno >= MAXMIDIINDEV) + bug("sys_dispatchnextmidiin 2"); + parserp = parser + portno; + outlet_setstacklim(); + + if (byte >= MIDI_CLOCK) + { + /* realtime message */ + inmidi_realtimein(portno, byte); + } + else + { + if (byte & 0x80) + { + /* status byte */ + inmidi_byte(portno, byte); + if (byte == MIDI_TUNEREQUEST || byte == MIDI_RESERVED1 || + byte == MIDI_RESERVED2) + { + /* system messages clear running status, + rest are handled in the data byte section below */ + parserp->mp_status = 0; + } + else if (byte == MIDI_SYSEX) + { + inmidi_sysex(portno, byte); + parserp->mp_status = byte; + } + else if (byte == MIDI_SYSEXEND) + { + inmidi_sysex(portno, byte); + parserp->mp_status = 0; + } + else + { + /* channel message or system message not handled here */ + parserp->mp_status = byte; + } + parserp->mp_gotbyte1 = 0; + } + else if (parserp->mp_status < MIDI_NOTEOFF) + { + /* running status w/out prev status byte or other invalid message */ + error("dropping unexpected midi byte %02X", byte); + } + else + { + int status, chan, byte1, gotbyte1; + /* data byte */ + inmidi_byte(portno, byte); + status = (parserp->mp_status >= MIDI_SYSEX ? + parserp->mp_status : (parserp->mp_status & 0xf0)); + chan = (parserp->mp_status & 0x0f); + byte1 = parserp->mp_byte1; + gotbyte1 = parserp->mp_gotbyte1; + switch (status) + { + case MIDI_NOTEOFF: + if (gotbyte1) + inmidi_noteon(portno, chan, byte1, 0), + parserp->mp_gotbyte1 = 0; + else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1; + break; + case MIDI_NOTEON: + if (gotbyte1) + inmidi_noteon(portno, chan, byte1, byte), + parserp->mp_gotbyte1 = 0; + else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1; + break; + case MIDI_POLYAFTERTOUCH: + if (gotbyte1) + inmidi_polyaftertouch(portno, chan, byte1, byte), + parserp->mp_gotbyte1 = 0; + else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1; + break; + case MIDI_CONTROLCHANGE: + if (gotbyte1) + inmidi_controlchange(portno, chan, byte1, byte), + parserp->mp_gotbyte1 = 0; + else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1; + break; + case MIDI_PROGRAMCHANGE: + inmidi_programchange(portno, chan, byte); + break; + case MIDI_AFTERTOUCH: + inmidi_aftertouch(portno, chan, byte); + break; + case MIDI_PITCHBEND: + if (gotbyte1) + inmidi_pitchbend(portno, chan, ((byte << 7) + byte1)), + parserp->mp_gotbyte1 = 0; + else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1; + break; + case MIDI_SYSEX: + inmidi_sysex(portno, byte); + break; + + /* We'll need another status byte before letting MIDI in + again (no running status across "system" messages). */ + case MIDI_TIMECODE: + parserp->mp_status = 0; + break; + case MIDI_SONGPOS: + if (gotbyte1) + parserp->mp_gotbyte1 = 0, parserp->mp_status = 0; + else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1; + break; + case MIDI_SONGSELECT: + parserp->mp_status = 0; + break; + } + } + } + midi_intail = (midi_intail + 1 == MIDIQSIZE ? 0 : midi_intail + 1); +} + +void sys_pollmidiinqueue(void) +{ +#ifdef TEST_DEJITTER + static int db = 0; +#endif + double logicaltime = .001 * clock_gettimesince(sys_midiinittime); +#ifdef TEST_DEJITTER + if (midi_inhead == midi_intail) + db = 0; +#endif + while (midi_inhead != midi_intail) + { +#ifdef TEST_DEJITTER + if (!db) + { + post("in del %f, logicaltime %f, RT %f adcminusRT %f", + (midi_inqueue[midi_intail].q_time - logicaltime), + logicaltime, sys_getrealtime(), sys_adctimeminusrealtime); + db = 1; + } +#endif +#if 0 + if (midi_inqueue[midi_intail].q_time <= logicaltime - 0.007) + post("late %f", + 1000 * (logicaltime - midi_inqueue[midi_intail].q_time)); +#endif + if (midi_inqueue[midi_intail].q_time <= logicaltime) + { +#if 0 + post("diff %f", + 1000* (logicaltime - midi_inqueue[midi_intail].q_time)); +#endif + sys_dispatchnextmidiin(); + } + else break; + } +} + + /* this should be called from the system dependent MIDI code when a byte + comes in, as a result of our calling sys_poll_midi. We stick it on a + timetag queue and dispatch it at the appropriate logical time. */ +void sys_midibytein(int portno, int byte) +{ + static int warned = 0; + t_midiqelem *midiqelem; + int newhead = midi_inhead +1; + if (newhead == MIDIQSIZE) + newhead = 0; + /* if FIFO is full flush an element to make room */ + if (newhead == midi_intail) + { + if (!warned) + { + post("warning: MIDI timing FIFO overflowed"); + warned = 1; + } + sys_dispatchnextmidiin(); + } + midi_inqueue[midi_inhead].q_portno = portno; + midi_inqueue[midi_inhead].q_onebyte = 1; + midi_inqueue[midi_inhead].q_byte1 = byte; + midi_inqueue[midi_inhead].q_time = sys_getmidiinrealtime(); + midi_inhead = newhead; + sys_pollmidiinqueue(); +} + +void sys_pollmidiqueue(void) +{ +#if 0 + static double lasttime; + double newtime = sys_getrealtime(); + if (newtime - lasttime > 0.007) + post("delay %d", (int)(1000 * (newtime - lasttime))); + lasttime = newtime; +#endif +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + sys_alsa_poll_midi(); + else +#endif /* ALSA */ + sys_poll_midi(); /* OS dependent poll for MIDI input */ + sys_pollmidioutqueue(); + sys_pollmidiinqueue(); +} + +/******************** dialog window and device listing ********************/ + +#define MAXNDEV 20 +#define DEVDESCSIZE 80 + +#define DEVONSET 1 /* To agree with command line flags, normally start at 1 */ + + +#ifdef USEAPI_ALSA +void midi_alsa_init(void); +#endif +#ifdef USEAPI_OSS +void midi_oss_init(void); +#endif + + /* last requested parameters */ +static int midi_nmidiindev; +static int midi_midiindev[MAXMIDIINDEV]; +static char midi_indevnames[MAXMIDIINDEV * DEVDESCSIZE]; +static int midi_nmidioutdev; +static int midi_midioutdev[MAXMIDIOUTDEV]; +static char midi_outdevnames[MAXMIDIINDEV * DEVDESCSIZE]; + +void sys_get_midi_apis(char *buf) +{ + int n = 0; + strcpy(buf, "{ "); +#ifdef USEAPI_OSS + sprintf(buf + strlen(buf), "{OSS-MIDI %d} ", API_DEFAULTMIDI); n++; +#endif +#ifdef USEAPI_ALSA + sprintf(buf + strlen(buf), "{ALSA-MIDI %d} ", API_ALSA); n++; +#endif + strcat(buf, "}"); + /* then again, if only one API (or none) we don't offer any choice. */ + if (n < 2) + strcpy(buf, "{}"); +} + +void sys_get_midi_params(int *pnmidiindev, int *pmidiindev, + int *pnmidioutdev, int *pmidioutdev) +{ + int i, devn; + *pnmidiindev = midi_nmidiindev; + for (i = 0; i < midi_nmidiindev; i++) + { + if ((devn = sys_mididevnametonumber(0, + &midi_indevnames[i * DEVDESCSIZE])) >= 0) + pmidiindev[i] = devn; + else pmidiindev[i] = midi_midiindev[i]; + } + *pnmidioutdev = midi_nmidioutdev; + for (i = 0; i < midi_nmidioutdev; i++) + { + if ((devn = sys_mididevnametonumber(1, + &midi_outdevnames[i * DEVDESCSIZE])) >= 0) + pmidioutdev[i] = devn; + else pmidioutdev[i] = midi_midioutdev[i]; + } +} + +static void sys_save_midi_params( + int nmidiindev, int *midiindev, + int nmidioutdev, int *midioutdev) +{ + int i; + midi_nmidiindev = nmidiindev; + for (i = 0; i < nmidiindev; i++) + { + midi_midiindev[i] = midiindev[i]; + sys_mididevnumbertoname(0, midiindev[i], + &midi_indevnames[i * DEVDESCSIZE], DEVDESCSIZE); + } + midi_nmidioutdev = nmidioutdev; + for (i = 0; i < nmidioutdev; i++) + { + midi_midioutdev[i] = midioutdev[i]; + sys_mididevnumbertoname(1, midioutdev[i], + &midi_outdevnames[i * DEVDESCSIZE], DEVDESCSIZE); + } +} + +void sys_open_midi(int nmidiindev, int *midiindev, + int nmidioutdev, int *midioutdev, int enable) +{ + if (enable) + { +#ifdef USEAPI_ALSA + midi_alsa_init(); +#endif +#ifdef USEAPI_OSS + midi_oss_init(); +#endif +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + sys_alsa_do_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev); + else +#endif /* ALSA */ + sys_do_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev); + } + sys_save_midi_params(nmidiindev, midiindev, + nmidioutdev, midioutdev); + + sys_vgui("set pd_whichmidiapi %d\n", sys_midiapi); + +} + + /* open midi using whatever parameters were last used */ +void sys_reopen_midi(void) +{ + int nmidiindev, midiindev[MAXMIDIINDEV]; + int nmidioutdev, midioutdev[MAXMIDIOUTDEV]; + sys_get_midi_params(&nmidiindev, midiindev, &nmidioutdev, midioutdev); + sys_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev, 1); +} + +void sys_listmididevs(void) +{ + char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE]; + int nindevs = 0, noutdevs = 0, i; + + sys_get_midi_devs(indevlist, &nindevs, outdevlist, &noutdevs, + MAXNDEV, DEVDESCSIZE); + + if (!nindevs) + post("no midi input devices found"); + else + { + post("MIDI input devices:"); + for (i = 0; i < nindevs; i++) + post("%d. %s", i+1, indevlist + i * DEVDESCSIZE); + } + if (!noutdevs) + post("no midi output devices found"); + else + { + post("MIDI output devices:"); + for (i = 0; i < noutdevs; i++) + post("%d. %s", i+DEVONSET, outdevlist + i * DEVDESCSIZE); + } +} + +void sys_set_midi_api(int which) +{ + switch (which) { +#ifdef USEAPI_ALSA + case(API_ALSA): break; +#endif +#ifndef FORCEAPI_ALSA + case(API_DEFAULTMIDI): break; +#endif + default: + if (sys_verbose) + post("Ignoring unknown MIDI-API %d", which); + return; + } + + sys_midiapi = which; + if (sys_verbose) + post("sys_midiapi %d", sys_midiapi); +} + +void glob_midi_properties(t_pd *dummy, t_floatarg flongform); +void midi_alsa_setndevs(int in, int out); + +void glob_midi_setapi(void *dummy, t_floatarg f) +{ + int newapi = f; + if (newapi != sys_midiapi) + { +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + sys_alsa_close_midi(); + else +#endif + sys_close_midi(); + sys_midiapi = newapi; + sys_reopen_midi(); + } +#ifdef USEAPI_ALSA + midi_alsa_setndevs(midi_nmidiindev, midi_nmidioutdev); +#endif + glob_midi_properties(0, (midi_nmidiindev > 1 || midi_nmidioutdev > 1)); +} + +extern t_class *glob_pdobject; + + /* start an midi settings dialog window */ +void glob_midi_properties(t_pd *dummy, t_floatarg flongform) +{ + char buf[1024 + 2 * MAXNDEV*(DEVDESCSIZE+4)]; + /* these are the devices you're using: */ + int nindev, midiindev[MAXMIDIINDEV]; + int noutdev, midioutdev[MAXMIDIOUTDEV]; + int midiindev1, midiindev2, midiindev3, midiindev4, midiindev5, + midiindev6, midiindev7, midiindev8, midiindev9, + midioutdev1, midioutdev2, midioutdev3, midioutdev4, midioutdev5, + midioutdev6, midioutdev7, midioutdev8, midioutdev9; + + /* these are all the devices on your system: */ + char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE]; + int nindevs = 0, noutdevs = 0, i; + + sys_get_midi_devs(indevlist, &nindevs, outdevlist, &noutdevs, + MAXNDEV, DEVDESCSIZE); + + sys_gui("global midi_indevlist; set midi_indevlist {none}\n"); + for (i = 0; i < nindevs; i++) + sys_vgui("lappend midi_indevlist {%s}\n", + indevlist + i * DEVDESCSIZE); + + sys_gui("global midi_outdevlist; set midi_outdevlist {none}\n"); + for (i = 0; i < noutdevs; i++) + sys_vgui("lappend midi_outdevlist {%s}\n", + outdevlist + i * DEVDESCSIZE); + + sys_get_midi_params(&nindev, midiindev, &noutdev, midioutdev); + + if (nindev > 1 || noutdev > 1) + flongform = 1; + + midiindev1 = (nindev > 0 && midiindev[0]>= 0 ? midiindev[0]+1 : 0); + midiindev2 = (nindev > 1 && midiindev[1]>= 0 ? midiindev[1]+1 : 0); + midiindev3 = (nindev > 2 && midiindev[2]>= 0 ? midiindev[2]+1 : 0); + midiindev4 = (nindev > 3 && midiindev[3]>= 0 ? midiindev[3]+1 : 0); + midiindev5 = (nindev > 4 && midiindev[4]>= 0 ? midiindev[4]+1 : 0); + midiindev6 = (nindev > 5 && midiindev[5]>= 0 ? midiindev[5]+1 : 0); + midiindev7 = (nindev > 6 && midiindev[6]>= 0 ? midiindev[6]+1 : 0); + midiindev8 = (nindev > 7 && midiindev[7]>= 0 ? midiindev[7]+1 : 0); + midiindev9 = (nindev > 8 && midiindev[8]>= 0 ? midiindev[8]+1 : 0); + midioutdev1 = (noutdev > 0 && midioutdev[0]>= 0 ? midioutdev[0]+1 : 0); + midioutdev2 = (noutdev > 1 && midioutdev[1]>= 0 ? midioutdev[1]+1 : 0); + midioutdev3 = (noutdev > 2 && midioutdev[2]>= 0 ? midioutdev[2]+1 : 0); + midioutdev4 = (noutdev > 3 && midioutdev[3]>= 0 ? midioutdev[3]+1 : 0); + midioutdev5 = (noutdev > 4 && midioutdev[4]>= 0 ? midioutdev[4]+1 : 0); + midioutdev6 = (noutdev > 5 && midioutdev[5]>= 0 ? midioutdev[5]+1 : 0); + midioutdev7 = (noutdev > 6 && midioutdev[6]>= 0 ? midioutdev[6]+1 : 0); + midioutdev8 = (noutdev > 7 && midioutdev[7]>= 0 ? midioutdev[7]+1 : 0); + midioutdev9 = (noutdev > 8 && midioutdev[8]>= 0 ? midioutdev[8]+1 : 0); + +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + sprintf(buf, +"pdtk_alsa_midi_dialog %%s \ +%d %d %d %d %d %d %d %d \ +%d 1\n", + midiindev1, midiindev2, midiindev3, midiindev4, + midioutdev1, midioutdev2, midioutdev3, midioutdev4, + (flongform != 0)); + else +#endif + sprintf(buf, +"pdtk_midi_dialog %%s \ +%d %d %d %d %d %d %d %d %d \ +%d %d %d %d %d %d %d %d %d \ +%d\n", + midiindev1, midiindev2, midiindev3, midiindev4, midiindev5, + midiindev6, midiindev7, midiindev8, midiindev9, + midioutdev1, midioutdev2, midioutdev3, midioutdev4, midioutdev5, + midioutdev6, midioutdev7, midioutdev8, midioutdev9, + (flongform != 0)); + + gfxstub_deleteforkey(0); + gfxstub_new(&glob_pdobject, (void *)glob_midi_properties, buf); +} + + /* new values from dialog window */ +void glob_midi_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) +{ + int nmidiindev, midiindev[MAXMIDIINDEV]; + int nmidioutdev, midioutdev[MAXMIDIOUTDEV]; + int i, nindev, noutdev; + int newmidiindev[9], newmidioutdev[9]; + int alsadevin, alsadevout; + + for (i = 0; i < 9; i++) + { + newmidiindev[i] = atom_getfloatarg(i, argc, argv); + newmidioutdev[i] = atom_getfloatarg(i+9, argc, argv); + } + + for (i = 0, nindev = 0; i < 9; i++) + { + if (newmidiindev[i] > 0) + { + newmidiindev[nindev] = newmidiindev[i]-1; + nindev++; + } + } + for (i = 0, noutdev = 0; i < 9; i++) + { + if (newmidioutdev[i] > 0) + { + newmidioutdev[noutdev] = newmidioutdev[i]-1; + noutdev++; + } + } + alsadevin = atom_getfloatarg(18, argc, argv); + alsadevout = atom_getfloatarg(19, argc, argv); +#ifdef USEAPI_ALSA + /* invent a story so that saving/recalling "settings" will + be able to restore the number of devices. ALSA MIDI handling + uses its own set of variables. LATER figure out how to get + this to work coherently */ + if (sys_midiapi == API_ALSA) + { + nindev = alsadevin; + noutdev = alsadevout; + for (i = 0; i < nindev; i++) + newmidiindev[i] = i; + for (i = 0; i < noutdev; i++) + newmidioutdev[i] = i; + } +#endif + sys_save_midi_params(nindev, newmidiindev, + noutdev, newmidioutdev); +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + { + sys_alsa_close_midi(); + sys_open_midi(alsadevin, newmidiindev, alsadevout, newmidioutdev, 1); + } + else +#endif + { + sys_close_midi(); + sys_open_midi(nindev, newmidiindev, noutdev, newmidioutdev, 1); + } + +} + +void sys_get_midi_devs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, + int maxndevs, int devdescsize) +{ + +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + midi_alsa_getdevs(indevlist, nindevs, outdevlist, noutdevs, + maxndevs, devdescsize); + else +#endif /* ALSA */ + midi_getdevs(indevlist, nindevs, outdevlist, noutdevs, maxndevs, devdescsize); +} + +/* convert a device name to a (1-based) device number. (Output device if +'output' parameter is true, otherwise input device). Negative on failure. */ +int sys_mididevnametonumber(int output, const char *name) +{ + char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE]; + int nindevs = 0, noutdevs = 0, i; + + sys_get_midi_devs(indevlist, &nindevs, outdevlist, &noutdevs, + MAXNDEV, DEVDESCSIZE); + + if (output) + { + /* try first for exact match */ + for (i = 0; i < noutdevs; i++) + if (!strcmp(name, outdevlist + i * DEVDESCSIZE)) + return (i); + /* failing that, a match up to end of shorter string */ + for (i = 0; i < noutdevs; i++) + { + unsigned int comp = strlen(name); + if (comp > strlen(outdevlist + i * DEVDESCSIZE)) + comp = strlen(outdevlist + i * DEVDESCSIZE); + if (!strncmp(name, outdevlist + i * DEVDESCSIZE, comp)) + return (i); + } + } + else + { + for (i = 0; i < nindevs; i++) + if (!strcmp(name, indevlist + i * DEVDESCSIZE)) + return (i); + for (i = 0; i < nindevs; i++) + { + unsigned int comp = strlen(name); + if (comp > strlen(indevlist + i * DEVDESCSIZE)) + comp = strlen(indevlist + i * DEVDESCSIZE); + if (!strncmp(name, indevlist + i * DEVDESCSIZE, comp)) + return (i); + } + } + return (-1); +} + +/* convert a (1-based) device number to a device name. (Output device if +'output' parameter is true, otherwise input device). Empty string on failure. */ +void sys_mididevnumbertoname(int output, int devno, char *name, int namesize) +{ + char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE]; + int nindevs = 0, noutdevs = 0, i; + if (devno < 0) + { + *name = 0; + return; + } + sys_get_midi_devs(indevlist, &nindevs, outdevlist, &noutdevs, + MAXNDEV, DEVDESCSIZE); + if (output && (devno < noutdevs)) + strncpy(name, outdevlist + devno * DEVDESCSIZE, namesize); + else if (!output && (devno < nindevs)) + strncpy(name, indevlist + devno * DEVDESCSIZE, namesize); + else *name = 0; + name[namesize-1] = 0; +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_midi_alsa.c b/ports/camomile/source/LibPd/pure-data/src/s_midi_alsa.c new file mode 100644 index 00000000..0c6bba90 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_midi_alsa.c @@ -0,0 +1,287 @@ +/* Copyright (c) 1997-1999 Guenter Geiger, Miller Puckette, Larry Troxler, +* Winfried Ritsch, Karl MacMillan, and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* MIDI I/O for Linux using ALSA */ + +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include "m_pd.h" +#include "s_stuff.h" + +/* full status byte definitions in s_midi.c */ +/* channel voice messages */ +#define MIDI_NOTEOFF 0x80 +#define MIDI_NOTEON 0x90 +#define MIDI_POLYAFTERTOUCH 0xa0 +#define MIDI_CONTROLCHANGE 0xb0 +#define MIDI_PROGRAMCHANGE 0xc0 +#define MIDI_AFTERTOUCH 0xd0 +#define MIDI_PITCHBEND 0xe0 +/* system common messages */ +#define MIDI_SYSEX 0xf0 +#define MIDI_TIMECODE 0xf1 +#define MIDI_SONGPOS 0xf2 +#define MIDI_SONGSELECT 0xf3 + +//the maximum length of input messages +#ifndef ALSA_MAX_EVENT_SIZE +#define ALSA_MAX_EVENT_SIZE 512 +#endif + +static int alsa_nmidiin; +static int alsa_midiinfd[MAXMIDIINDEV]; +static int alsa_nmidiout; +static int alsa_midioutfd[MAXMIDIOUTDEV]; + +static snd_seq_t *midi_handle; + +static snd_midi_event_t *midiev; + +void sys_alsa_do_open_midi(int nmidiin, int *midiinvec, + int nmidiout, int *midioutvec) +{ + + char portname[50]; + int err = 0; + int client; + int i; + snd_seq_client_info_t *alsainfo; + + alsa_nmidiin = 0; + alsa_nmidiout = 0; + + if (nmidiout == 0 && nmidiin == 0) return; + + if (nmidiin > MAXMIDIINDEV ) + { + post("midi input ports reduced to maximum %d", MAXMIDIINDEV); + nmidiin = MAXMIDIINDEV; + } + if (nmidiout > MAXMIDIOUTDEV) + { + post("midi output ports reduced to maximum %d", MAXMIDIOUTDEV); + nmidiout = MAXMIDIOUTDEV; + } + + if (nmidiin > 0 && nmidiout > 0) + err = snd_seq_open(&midi_handle, "default", SND_SEQ_OPEN_DUPLEX, 0); + else if (nmidiin > 0) + err = snd_seq_open(&midi_handle, "default", SND_SEQ_OPEN_INPUT, 0); + else if (nmidiout > 0) + err = snd_seq_open(&midi_handle, "default", SND_SEQ_OPEN_OUTPUT, 0); + + if (err != 0) + { + sys_setalarm(1000000); + post("couldn't open alsa sequencer"); + return; + } + for (i = 0; i < nmidiin; i++) + { + int port; + sprintf(portname, "Pure Data Midi-In %d", i+1); + port = snd_seq_create_simple_port(midi_handle,portname, + SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, + SND_SEQ_PORT_TYPE_APPLICATION); + alsa_midiinfd[i] = port; + if (port < 0) goto error; + } + + for (i = 0; i < nmidiout; i++) + { + int port; + sprintf(portname,"Pure Data Midi-Out %d", i+1); + port = snd_seq_create_simple_port(midi_handle,portname, + SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_APPLICATION); + alsa_midioutfd[i] = port; + if (port < 0) goto error; + } + + snd_seq_client_info_malloc(&alsainfo); + snd_seq_get_client_info(midi_handle, alsainfo); + snd_seq_client_info_set_name(alsainfo,"Pure Data"); + client = snd_seq_client_info_get_client(alsainfo); + snd_seq_set_client_info(midi_handle, alsainfo); + snd_seq_client_info_free(alsainfo); + post("opened alsa client %d in:%d out:%d", client, nmidiin, nmidiout); + sys_setalarm(0); + snd_midi_event_new(ALSA_MAX_EVENT_SIZE, &midiev); + alsa_nmidiout = nmidiout; + alsa_nmidiin = nmidiin; + + return; + error: + sys_setalarm(1000000); + post("couldn't open alsa MIDI output device"); + return; +} + +void sys_alsa_putmidimess(int portno, int a, int b, int c) +{ + if (portno >= 0 && portno < alsa_nmidiout) + { + snd_seq_event_t ev; + snd_seq_ev_clear(&ev); + int status = a & 0xf0; + int channel = a & 0x0f; + status = (status >= MIDI_SYSEX) ? status : (status & 0xf0); + switch (status) + { + case MIDI_NOTEON: + snd_seq_ev_set_noteon(&ev, channel, b, c); + break; + case MIDI_NOTEOFF: + snd_seq_ev_set_noteoff(&ev, channel, b, c); + break; + case MIDI_POLYAFTERTOUCH: + snd_seq_ev_set_chanpress(&ev, channel, b); + break; + case MIDI_CONTROLCHANGE: + snd_seq_ev_set_controller(&ev, channel, b, c); + break; + case MIDI_PROGRAMCHANGE: + snd_seq_ev_set_pgmchange(&ev, channel, b); + break; + case MIDI_AFTERTOUCH: + snd_seq_ev_set_chanpress(&ev, channel, b); + break; + case MIDI_PITCHBEND: + /* b and c are already correct but alsa needs to recalculate them */ + snd_seq_ev_set_pitchbend(&ev, channel, (((c<<7)|b)-8192)); + break; + case MIDI_TIMECODE: + ev.type = SND_SEQ_EVENT_QFRAME; + snd_seq_ev_set_fixed(&ev); + ev.data.raw8.d[0] = a & 0xff; /* status */ + ev.data.raw8.d[1] = b & 0x7f; /* data */ + break; + case MIDI_SONGPOS: + ev.type = SND_SEQ_EVENT_SONGPOS; + snd_seq_ev_set_fixed(&ev); + ev.data.raw8.d[0] = a & 0xff; /* status */ + ev.data.raw8.d[1] = b & 0x7f; /* data */ + ev.data.raw8.d[2] = c & 0x7f; /* data */ + break; + case MIDI_SONGSELECT: + ev.type = SND_SEQ_EVENT_SONGSEL; + snd_seq_ev_set_fixed(&ev); + ev.data.raw8.d[0] = a & 0xff; /* status */ + ev.data.raw8.d[1] = b & 0x7f; /* data */ + break; + default: + bug("couldn't put alsa midi message"); + break; + } + snd_seq_ev_set_direct(&ev); + snd_seq_ev_set_subs(&ev); + snd_seq_ev_set_source(&ev, alsa_midioutfd[portno]); + snd_seq_event_output_direct(midi_handle, &ev); + } + //post("%d %d %d\n", a, b, c); +} + +void sys_alsa_putmidibyte(int portno, int byte) +{ + static snd_midi_event_t *dev = NULL; + int res; + snd_seq_event_t ev; + if (!dev) { + snd_midi_event_new(ALSA_MAX_EVENT_SIZE, &dev); + //assert(dev); + snd_midi_event_init(dev); + } + snd_seq_ev_clear(&ev); + res = snd_midi_event_encode_byte(dev, byte, &ev); + if (res > 0 && ev.type != SND_SEQ_EVENT_NONE) { + // got a complete event, output it + snd_seq_ev_set_direct(&ev); + snd_seq_ev_set_subs(&ev); + snd_seq_ev_set_source(&ev, alsa_midioutfd[portno]); + snd_seq_event_output_direct(midi_handle, &ev); + } + if (res != 0) + // reinitialize the parser + snd_midi_event_init(dev); +} + + + /* this version uses the asynchronous "read()" ... */ +void sys_alsa_poll_midi(void) +{ + unsigned char buf[ALSA_MAX_EVENT_SIZE]; + int count, alsa_source; + int i; + snd_seq_event_t *midievent = NULL; + + if (alsa_nmidiout == 0 && alsa_nmidiin == 0) return; + + snd_midi_event_init(midiev); + + if (!alsa_nmidiout && !alsa_nmidiin) return; + count = snd_seq_event_input_pending(midi_handle, 1); + if (count != 0) + count = snd_seq_event_input(midi_handle, &midievent); + if (midievent != NULL) + { + count = snd_midi_event_decode(midiev, buf, sizeof(buf), midievent); + alsa_source = midievent->dest.port; + for(i = 0; i < count; i++) + sys_midibytein(alsa_source, (buf[i] & 0xff)); + //post("received %d midi bytes\n", count); + } +} + +void sys_alsa_close_midi() +{ + alsa_nmidiin = alsa_nmidiout = 0; + if (midi_handle) + { + snd_seq_close(midi_handle); + midi_handle = NULL; + if (midiev) + { + snd_midi_event_free(midiev); + midiev = NULL; + } + } +} + +static int alsa_nmidiindevs = 1, alsa_nmidioutdevs = 1; + +void midi_alsa_init(void) +{ +} + +void midi_alsa_setndevs(int in, int out) +{ + alsa_nmidiindevs = in; + alsa_nmidioutdevs = out; +} + +void midi_alsa_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int maxndev, int devdescsize) +{ + int i, ndev; + if ((ndev = alsa_nmidiindevs) > maxndev) + ndev = maxndev; + for (i = 0; i < ndev; i++) + sprintf(indevlist + i * devdescsize, "ALSA MIDI device #%d", i+1); + *nindevs = ndev; + + if ((ndev = alsa_nmidioutdevs) > maxndev) + ndev = maxndev; + for (i = 0; i < ndev; i++) + sprintf(outdevlist + i * devdescsize, "ALSA MIDI device #%d", i+1); + *noutdevs = ndev; +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_midi_dummy.c b/ports/camomile/source/LibPd/pure-data/src/s_midi_dummy.c new file mode 100644 index 00000000..0ab463ef --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_midi_dummy.c @@ -0,0 +1,34 @@ +/* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler, +* Winfried Ritsch, Karl MacMillan, and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. + + this file is a dummy for systems without any MIDI support + +*/ + +void sys_do_open_midi(int nmidiin, int *midiinvec, + int nmidiout, int *midioutvec) +{ +} + +void sys_close_midi( void) +{ +} + +void sys_putmidimess(int portno, int a, int b, int c) +{ +} + +void sys_putmidibyte(int portno, int byte) +{ +} + +void sys_poll_midi(void) +{ +} + +void midi_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int maxndev, int devdescsize) +{ +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_midi_oss.c b/ports/camomile/source/LibPd/pure-data/src/s_midi_oss.c new file mode 100644 index 00000000..2f3f23e7 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_midi_oss.c @@ -0,0 +1,311 @@ +/* Copyright (c) 1997-1999 Guenter Geiger, Miller Puckette, Larry Troxler, +* Winfried Ritsch, Karl MacMillan, and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* MIDI I/O for Linux using OSS */ + +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include "m_pd.h" +#include "s_stuff.h" + +#define NSEARCH 10 +static int oss_nmidiindevs, oss_nmidioutdevs; +static char oss_indevnames[NSEARCH][4], oss_outdevnames[NSEARCH][4]; +static int oss_nmidiin; +static int oss_midiinfd[MAXMIDIINDEV]; +static int oss_nmidiout; +static int oss_midioutfd[MAXMIDIOUTDEV]; + +static void oss_midiout(int fd, int n) +{ + char b = n; + if ((write(fd, (char *) &b, 1)) != 1) + perror("midi write"); +} + +#define O_MIDIFLAG O_NDELAY + +void sys_do_open_midi(int nmidiin, int *midiinvec, + int nmidiout, int *midioutvec) +{ + int i; + for (i = 0; i < nmidiout; i++) + oss_midioutfd[i] = -1; + for (i = 0, oss_nmidiin = 0; i < nmidiin; i++) + { + int fd = -1, j, outdevindex = -1; + char namebuf[80]; + int devno = midiinvec[i]; + if (devno < 0 || devno >= oss_nmidiindevs) + continue; + for (j = 0; j < nmidiout; j++) + if (midioutvec[j] >= 0 && midioutvec[j] <= oss_nmidioutdevs + && !strcmp(oss_outdevnames[midioutvec[j]], + oss_indevnames[devno])) + outdevindex = j; + + sprintf(namebuf, "/dev/midi%s", oss_indevnames[devno]); + + /* try to open the device for read/write. */ + if (outdevindex >= 0) + { + sys_setalarm(1000000); + fd = open(namebuf, O_RDWR | O_MIDIFLAG); + if (sys_verbose) + post("tried to open %s read/write; got %d\n", + namebuf, fd); + if (outdevindex >= 0 && fd >= 0) + oss_midioutfd[outdevindex] = fd; + } + /* OK, try read-only */ + if (fd < 0) + { + sys_setalarm(1000000); + fd = open(namebuf, O_RDONLY | O_MIDIFLAG); + if (sys_verbose) + post("tried to open %s read-only; got %d\n", + namebuf, fd); + } + if (fd >= 0) + oss_midiinfd[oss_nmidiin++] = fd; + else post("couldn't open MIDI input device %s", namebuf); + } + for (i = 0, oss_nmidiout = 0; i < nmidiout; i++) + { + int fd = oss_midioutfd[i]; + char namebuf[80]; + int devno = midioutvec[i]; + if (devno < 0 || devno >= oss_nmidioutdevs) + continue; + sprintf(namebuf, "/dev/midi%s", oss_outdevnames[devno]); + if (fd < 0) + { + sys_setalarm(1000000); + fd = open(namebuf, O_WRONLY | O_MIDIFLAG); + if (sys_verbose) + post("tried to open %s write-only; got %d\n", + namebuf, fd); + } + if (fd >= 0) + oss_midioutfd[oss_nmidiout++] = fd; + else post("couldn't open MIDI output device %s", namebuf); + } + + if (oss_nmidiin < nmidiin || oss_nmidiout < nmidiout || sys_verbose) + post("opened %d MIDI input device(s) and %d MIDI output device(s).", + oss_nmidiin, oss_nmidiout); + + sys_setalarm(0); +} + +#define md_msglen(x) (((x)<0xC0)?2:((x)<0xE0)?1:((x)<0xF0)?2:\ + ((x)==0xF2)?2:((x)<0xF4)?1:0) + +void sys_putmidimess(int portno, int a, int b, int c) +{ + if (portno >= 0 && portno < oss_nmidiout) + { + switch (md_msglen(a)) + { + case 2: + oss_midiout(oss_midioutfd[portno],a); + oss_midiout(oss_midioutfd[portno],b); + oss_midiout(oss_midioutfd[portno],c); + return; + case 1: + oss_midiout(oss_midioutfd[portno],a); + oss_midiout(oss_midioutfd[portno],b); + return; + case 0: + oss_midiout(oss_midioutfd[portno],a); + return; + }; + } +} + +void sys_putmidibyte(int portno, int byte) +{ + if (portno >= 0 && portno < oss_nmidiout) + oss_midiout(oss_midioutfd[portno], byte); +} + +#if 0 /* this is the "select" version which doesn't work with OSS + driver for emu10k1 (it doesn't implement select.) */ +void sys_poll_midi(void) +{ + int i, throttle = 100; + struct timeval timout; + int did = 1, maxfd = 0; + while (did) + { + fd_set readset, writeset, exceptset; + did = 0; + if (throttle-- < 0) + break; + timout.tv_sec = 0; + timout.tv_usec = 0; + + FD_ZERO(&writeset); + FD_ZERO(&readset); + FD_ZERO(&exceptset); + for (i = 0; i < oss_nmidiin; i++) + { + if (oss_midiinfd[i] > maxfd) + maxfd = oss_midiinfd[i]; + FD_SET(oss_midiinfd[i], &readset); + } + select(maxfd+1, &readset, &writeset, &exceptset, &timout); + for (i = 0; i < oss_nmidiin; i++) + if (FD_ISSET(oss_midiinfd[i], &readset)) + { + char c; + int ret = read(oss_midiinfd[i], &c, 1); + if (ret <= 0) + fprintf(stderr, "Midi read error\n"); + else sys_midibytein(i, (c & 0xff)); + did = 1; + } + } +} +#else + + /* this version uses the asynchronous "read()" ... */ +void sys_poll_midi(void) +{ + int i, throttle = 100; + struct timeval timout; + int did = 1, maxfd = 0; + while (did) + { + fd_set readset, writeset, exceptset; + did = 0; + if (throttle-- < 0) + break; + for (i = 0; i < oss_nmidiin; i++) + { + char c; + int ret = read(oss_midiinfd[i], &c, 1); + if (ret < 0) + { + if (errno != EAGAIN) + perror("MIDI"); + } + else if (ret != 0) + { + sys_midibytein(i, (c & 0xff)); + did = 1; + } + } + } +} +#endif + +void sys_close_midi() +{ + int i; + for (i = 0; i < oss_nmidiin; i++) + close(oss_midiinfd[i]); + for (i = 0; i < oss_nmidiout; i++) + close(oss_midioutfd[i]); + oss_nmidiin = oss_nmidiout = 0; +} + +void midi_oss_init(void) +{ + int fd, devno; + struct stat statbuf; + char namebuf[80]; + /* we only try to detect devices before trying to open them, because + when they're open, they migth not be possible to reopen here */ + static int initted = 0; + if (initted) + return; + initted = 1; + oss_nmidiindevs = oss_nmidioutdevs = 0; + + for (devno = 0; devno < NSEARCH; devno++) + { + if (devno == 0) + { + /* try to open the device for reading */ + fd = open("/dev/midi", O_RDONLY | O_NDELAY); + if (fd >= 0) + { + close(fd); + strcpy(oss_indevnames[oss_nmidiindevs++], ""); + } + fd = open("/dev/midi", O_WRONLY | O_NDELAY); + if (fd >= 0) + { + close(fd); + strcpy(oss_outdevnames[oss_nmidioutdevs++], ""); + } + } + if (oss_nmidiindevs >= NSEARCH || oss_nmidioutdevs >= NSEARCH) + break; + + sprintf(namebuf, "/dev/midi%d", devno); + fd = open(namebuf, O_RDONLY | O_NDELAY); + if (fd >= 0) + { + close(fd); + sprintf(oss_indevnames[oss_nmidiindevs++], "%d", devno); + } + fd = open(namebuf, O_WRONLY | O_NDELAY); + if (fd >= 0) + { + close(fd); + sprintf(oss_outdevnames[oss_nmidioutdevs++], "%d", devno); + } + if (oss_nmidiindevs >= NSEARCH || oss_nmidioutdevs >= NSEARCH) + break; + + sprintf(namebuf, "/dev/midi%2.2d", devno); + fd = open(namebuf, O_RDONLY | O_NDELAY); + if (fd >= 0) + { + close(fd); + sprintf(oss_indevnames[oss_nmidiindevs++], "%d", devno); + } + fd = open(namebuf, O_WRONLY | O_NDELAY); + if (fd >= 0) + { + close(fd); + sprintf(oss_outdevnames[oss_nmidioutdevs++], "%d", devno); + } + if (oss_nmidiindevs >= NSEARCH || oss_nmidioutdevs >= NSEARCH) + break; + + } +} + +void midi_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int maxndev, int devdescsize) +{ + int i, ndev; + midi_oss_init(); + + if ((ndev = oss_nmidiindevs) > maxndev) + ndev = maxndev; + for (i = 0; i < ndev; i++) + sprintf(indevlist + i * devdescsize, + "/dev/midi%s", oss_indevnames[i]); + *nindevs = ndev; + + if ((ndev = oss_nmidioutdevs) > maxndev) + ndev = maxndev; + for (i = 0; i < ndev; i++) + sprintf(outdevlist + i * devdescsize, + "/dev/midi%s", oss_outdevnames[i]); + *noutdevs = ndev; +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_midi_pm.c b/ports/camomile/source/LibPd/pure-data/src/s_midi_pm.c new file mode 100644 index 00000000..94bb007d --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_midi_pm.c @@ -0,0 +1,358 @@ +/* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler, +* Winfried Ritsch, Karl MacMillan, and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. + + this file calls portmidi to do MIDI I/O for MSW and Mac OSX. + +*/ + +#include "m_pd.h" +#include "s_stuff.h" +#include +#ifdef HAVE_UNISTD_H +#include +#include +#ifndef _WIN32 +#include +#endif /* _WIN32 */ +#endif /* HAVE_UNISTD_H */ +#include +#include +#include +#include "portmidi.h" +#include "porttime.h" + +/* full status byte definitions in s_midi.c */ +/* channel voice messages */ +#define MIDI_NOTEOFF 0x80 +#define MIDI_NOTEON 0x90 +#define MIDI_POLYAFTERTOUCH 0xa0 +#define MIDI_CONTROLCHANGE 0xb0 +#define MIDI_PROGRAMCHANGE 0xc0 +#define MIDI_AFTERTOUCH 0xd0 +#define MIDI_PITCHBEND 0xe0 +/* system common messages */ +#define MIDI_SYSEX 0xf0 +#define MIDI_TIMECODE 0xf1 +#define MIDI_SONGPOS 0xf2 +#define MIDI_SONGSELECT 0xf3 +#define MIDI_SYSEXEND 0xf7 + +static PmStream *mac_midiindevlist[MAXMIDIINDEV]; +static PmStream *mac_midioutdevlist[MAXMIDIOUTDEV]; +static int mac_nmidiindev; +static int mac_nmidioutdev; + +void sys_do_open_midi(int nmidiin, int *midiinvec, + int nmidiout, int *midioutvec) +{ + int i = 0, j, devno; + int n = 0; + PmError err; + + Pt_Start(1, 0, 0); /* start a timer with millisecond accuracy */ + + mac_nmidiindev = 0; + for (i = 0; i < nmidiin; i++) + { + for (j = 0, devno = 0; j < Pm_CountDevices(); j++) + { + const PmDeviceInfo *info = Pm_GetDeviceInfo(j); + if (info->input) + { + if (devno == midiinvec[i]) + { + err = Pm_OpenInput(&mac_midiindevlist[mac_nmidiindev], + j, NULL, 100, NULL, NULL); + if (err) + post("could not open midi input %d (%s): %s", + j, info->name, Pm_GetErrorText(err)); + else + { + /* disable default active sense filtering */ + Pm_SetFilter(mac_midiindevlist[mac_nmidiindev], 0); + if (sys_verbose) + post("midi input (%s) opened.", + info->name); + mac_nmidiindev++; + } + } + devno++; + } + } + } + + mac_nmidioutdev = 0; + for (i = 0; i < nmidiout; i++) + { + for (j = 0, devno = 0; j < Pm_CountDevices(); j++) + { + const PmDeviceInfo *info = Pm_GetDeviceInfo(j); + if (info->output) + { + if (devno == midioutvec[i]) + { + err = Pm_OpenOutput( + &mac_midioutdevlist[mac_nmidioutdev], + j, NULL, 0, NULL, NULL, 0); + if (err) + post("could not open midi output %d (%s): %s", + j, info->name, Pm_GetErrorText(err)); + else + { + if (sys_verbose) + post("midi output (%s) opened.", + info->name); + mac_nmidioutdev++; + } + } + devno++; + } + } + } +} + +void sys_close_midi( void) +{ + int i; + for (i = 0; i < mac_nmidiindev; i++) + Pm_Close(mac_midiindevlist[i]); + mac_nmidiindev = 0; + for (i = 0; i < mac_nmidioutdev; i++) + Pm_Close(mac_midioutdevlist[i]); + mac_nmidioutdev = 0; +} + +void sys_putmidimess(int portno, int a, int b, int c) +{ + PmEvent buffer; + /* fprintf(stderr, "put 1 msg %d %d\n", portno, mac_nmidioutdev); */ + if (portno >= 0 && portno < mac_nmidioutdev) + { + buffer.message = Pm_Message(a, b, c); + buffer.timestamp = 0; + /* fprintf(stderr, "put msg\n"); */ + Pm_Write(mac_midioutdevlist[portno], &buffer, 1); + } +} + +static void writemidi4(PortMidiStream* stream, int a, int b, int c, int d) +{ + PmEvent buffer; + buffer.timestamp = 0; + buffer.message = ((a & 0xff) | ((b & 0xff) << 8) + | ((c & 0xff) << 16) | ((d & 0xff) << 24)); + Pm_Write(stream, &buffer, 1); +} + + +void sys_putmidibyte(int portno, int byte) +{ + /* try to parse the bytes into MIDI messages so they can + fit into PortMidi buffers. */ + static int mess[4]; + static int nbytes = 0, sysex = 0, i; + if (byte > MIDI_SYSEXEND) + { + /* realtime */ + writemidi4(mac_midioutdevlist[portno], byte, 0, 0, 0); + } + else if (byte == MIDI_SYSEX) + { + /* sysex start */ + mess[0] = MIDI_SYSEX; + nbytes = 1; + sysex = 1; + } + else if (byte == MIDI_SYSEXEND) + { + /* sysex end */ + mess[nbytes] = byte; + for (i = nbytes+1; i < 4; i++) + mess[i] = 0; + writemidi4(mac_midioutdevlist[portno], + mess[0], mess[1], mess[2], mess[3]); + sysex = 0; + nbytes = 0; + } + else if (byte >= MIDI_NOTEOFF) + { + /* status byte */ + sysex = 0; + if (byte > MIDI_SONGSELECT) + { + /* 0 data bytes */ + writemidi4(mac_midioutdevlist[portno], byte, 0, 0, 0); + nbytes = 0; + } + else + { + /* 1 or 2 data bytes */ + mess[0] = byte; + nbytes = 1; + } + } + else if (sysex) + { + /* sysex data byte */ + mess[nbytes] = byte; + nbytes++; + if (nbytes == 4) + { + writemidi4(mac_midioutdevlist[portno], + mess[0], mess[1], mess[2], mess[3]); + nbytes = 0; + } + } + else if (nbytes) + { + /* channel or system message */ + int status = mess[0]; + if (status < MIDI_SYSEX) + status &= 0xf0; + if (status == MIDI_PROGRAMCHANGE || status == MIDI_AFTERTOUCH || + status == MIDI_TIMECODE || status == MIDI_SONGSELECT) + { + writemidi4(mac_midioutdevlist[portno], + mess[0], byte, 0, 0); + nbytes = (status < MIDI_SYSEX ? 1 : 0); + } + else + { + if (nbytes == 1) + { + mess[1] = byte; + nbytes = 2; + } + else + { + writemidi4(mac_midioutdevlist[portno], + mess[0], mess[1], byte, 0); + nbytes = (status < 0xf0 ? 1 : 0); + } + } + } +} + +/* this is non-zero if we are in the middle of transmitting sysex */ +int nd_sysex_mode = 0; + +/* send in 4 bytes of sysex data. if one of the bytes is sysex end + stop and unset nd_sysex_mode */ +void nd_sysex_inword(int midiindev, int status, int data1, int data2, int data3) +{ + if (nd_sysex_mode) { + sys_midibytein(midiindev, status); + if (status == MIDI_SYSEXEND) + nd_sysex_mode = 0; + } + + if (nd_sysex_mode) { + sys_midibytein(midiindev, data1); + if (data1 == MIDI_SYSEXEND) + nd_sysex_mode = 0; + } + + if (nd_sysex_mode) { + sys_midibytein(midiindev, data2); + if (data2 == MIDI_SYSEXEND) + nd_sysex_mode = 0; + } + + if (nd_sysex_mode) { + sys_midibytein(midiindev, data3); + if (data3 == MIDI_SYSEXEND) + nd_sysex_mode = 0; + } +} + +void sys_poll_midi(void) +{ + int i, nmess, throttle = 100; + PmEvent buffer; + for (i = 0; i < mac_nmidiindev; i++) + { + if(Pm_Poll(mac_midiindevlist[i])) + { + if (!throttle--) + goto overload; + nmess = Pm_Read(mac_midiindevlist[i], &buffer, 1); + if (nmess > 0) + { + int status = Pm_MessageStatus(buffer.message); + int data1 = Pm_MessageData1(buffer.message); + int data2 = Pm_MessageData2(buffer.message); + int data3 = ((buffer.message >> 24) & 0xff); + int msgtype = ((status & 0xf0) == 0xf0 ? + status : (status & 0xf0)); + + if (status > MIDI_SYSEXEND) + { + /* realtime message */ + sys_midibytein(i, status); + } + else if (nd_sysex_mode) + nd_sysex_inword(i, status, data1, data2, data3); + else switch (msgtype) + { + /* 2 data bytes */ + case MIDI_NOTEOFF: + case MIDI_NOTEON: + case MIDI_POLYAFTERTOUCH: + case MIDI_CONTROLCHANGE: + case MIDI_PITCHBEND: + case MIDI_SONGPOS: + sys_midibytein(i, status); + sys_midibytein(i, data1); + sys_midibytein(i, data2); + break; + /* 1 data byte */ + case MIDI_PROGRAMCHANGE: + case MIDI_AFTERTOUCH: + case MIDI_TIMECODE: + case MIDI_SONGSELECT: + sys_midibytein(i, status); + sys_midibytein(i, data1); + break; + /* no data bytes */ + case MIDI_SYSEX: + nd_sysex_mode = 1; + nd_sysex_inword(i, status, data1, data2, data3); + break; + /* all others */ + default: + sys_midibytein(i, status); + break; + } + } + else if (nmess != pmBufferOverflow) + break; + } + } + overload: ; +} + +void midi_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int maxndev, int devdescsize) +{ + int i, nindev = 0, noutdev = 0; + for (i = 0; i < Pm_CountDevices(); i++) + { + const PmDeviceInfo *info = Pm_GetDeviceInfo(i); + /* post("%d: %s, %s (%d,%d)", i, info->interf, info->name, + info->input, info->output); */ + if (info->input && nindev < maxndev) + { + strcpy(indevlist + nindev * devdescsize, info->name); + nindev++; + } + if (info->output && noutdev < maxndev) + { + strcpy(outdevlist + noutdev * devdescsize, info->name); + noutdev++; + } + } + *nindevs = nindev; + *noutdevs = noutdev; +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_path.c b/ports/camomile/source/LibPd/pure-data/src/s_path.c new file mode 100644 index 00000000..687c357d --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_path.c @@ -0,0 +1,712 @@ +/* Copyright (c) 1999 Guenter Geiger and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* + * This file implements the loader for linux, which includes + * a little bit of path handling. + * + * Generalized by MSP to provide an open_via_path function + * and lists of files for all purposes. + */ + +/* #define DEBUG(x) x */ +#define DEBUG(x) + +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#ifdef _WIN32 +#include +#include +#endif + +#ifdef _WIN32 +# include /* MSVC or mingw on windows */ +#elif defined(__linux__) || defined(__APPLE__) +# include /* linux, mac, mingw, cygwin */ +#else +# include /* BSDs for example */ +#endif + +#include +#include "m_pd.h" +#include "m_imp.h" +#include "s_stuff.h" +#include "s_utf8.h" +#include +#include +#include + +#ifdef _LARGEFILE64_SOURCE +# define open open64 +# define lseek lseek64 +# define fstat fstat64 +# define stat stat64 +#endif + + + /* change '/' characters to the system's native file separator */ +void sys_bashfilename(const char *from, char *to) +{ + char c; + while ((c = *from++)) + { +#ifdef _WIN32 + if (c == '/') c = '\\'; +#endif + *to++ = c; + } + *to = 0; +} + + /* change the system's native file separator to '/' characters */ +void sys_unbashfilename(const char *from, char *to) +{ + char c; + while ((c = *from++)) + { +#ifdef _WIN32 + if (c == '\\') c = '/'; +#endif + *to++ = c; + } + *to = 0; +} + +/* test if path is absolute or relative, based on leading /, env vars, ~, etc */ +int sys_isabsolutepath(const char *dir) +{ + if (dir[0] == '/' || dir[0] == '~' +#ifdef _WIN32 + || dir[0] == '%' || (dir[1] == ':' && dir[2] == '/') +#endif + ) + { + return 1; + } + else + { + return 0; + } +} + +/* expand env vars and ~ at the beginning of a path and make a copy to return */ +static void sys_expandpath(const char *from, char *to, int bufsize) +{ + if ((strlen(from) == 1 && from[0] == '~') || (strncmp(from,"~/", 2) == 0)) + { +#ifdef _WIN32 + const char *home = getenv("USERPROFILE"); +#else + const char *home = getenv("HOME"); +#endif + if (home) + { + strncpy(to, home, bufsize); + to[bufsize-1] = 0; + strncpy(to + strlen(to), from + 1, bufsize - strlen(to)); + to[bufsize-1] = 0; + } + else *to = 0; + } + else + { + strncpy(to, from, bufsize); + to[bufsize-1] = 0; + } +#ifdef _WIN32 + { + char *buf = alloca(bufsize); + ExpandEnvironmentStrings(to, buf, bufsize-1); + buf[bufsize-1] = 0; + strncpy(to, buf, bufsize); + to[bufsize-1] = 0; + } +#endif +} + +/******************* Utility functions used below ******************/ + +/*! + * \brief copy until delimiter + * + * \arg to destination buffer + * \arg to_len destination buffer length + * \arg from source buffer + * \arg delim string delimiter to stop copying on + * + * \return position after delimiter in string. If it was the last + * substring, return NULL. + */ +static const char *strtokcpy(char *to, size_t to_len, const char *from, char delim) +{ + unsigned int i = 0; + + for (; i < (to_len - 1) && from[i] && from[i] != delim; i++) + to[i] = from[i]; + to[i] = '\0'; + + if (i && from[i] != '\0') + return from + i + 1; + + return NULL; +} + +/* add a single item to a namelist. If "allowdup" is true, duplicates +may be added; othewise they're dropped. */ + +t_namelist *namelist_append(t_namelist *listwas, const char *s, int allowdup) +{ + t_namelist *nl, *nl2; + nl2 = (t_namelist *)(getbytes(sizeof(*nl))); + nl2->nl_next = 0; + nl2->nl_string = (char *)getbytes(strlen(s) + 1); + strcpy(nl2->nl_string, s); + sys_unbashfilename(nl2->nl_string, nl2->nl_string); + if (!listwas) + return (nl2); + else + { + for (nl = listwas; ;) + { + if (!allowdup && !strcmp(nl->nl_string, s)) + { + freebytes(nl2->nl_string, strlen(nl2->nl_string) + 1); + return (listwas); + } + if (!nl->nl_next) + break; + nl = nl->nl_next; + } + nl->nl_next = nl2; + } + return (listwas); +} + +/* add a colon-separated list of names to a namelist */ + +#ifdef _WIN32 +#define SEPARATOR ';' /* in MSW the natural separator is semicolon instead */ +#else +#define SEPARATOR ':' +#endif + +t_namelist *namelist_append_files(t_namelist *listwas, const char *s) +{ + const char *npos; + char temp[MAXPDSTRING]; + t_namelist *nl = listwas, *rtn = listwas; + + npos = s; + do + { + npos = strtokcpy(temp, sizeof(temp), npos, SEPARATOR); + if (! *temp) continue; + nl = namelist_append(nl, temp, 0); + } + while (npos); + return (nl); +} + +void namelist_free(t_namelist *listwas) +{ + t_namelist *nl, *nl2; + for (nl = listwas; nl; nl = nl2) + { + nl2 = nl->nl_next; + t_freebytes(nl->nl_string, strlen(nl->nl_string) + 1); + t_freebytes(nl, sizeof(*nl)); + } +} + +char *namelist_get(t_namelist *namelist, int n) +{ + int i; + t_namelist *nl; + for (i = 0, nl = namelist; i < n && nl; i++, nl = nl->nl_next) + ; + return (nl ? nl->nl_string : 0); +} + +int sys_usestdpath = 1; + +void sys_setextrapath(const char *p) +{ + char pathbuf[MAXPDSTRING]; + namelist_free(STUFF->st_staticpath); + /* add standard place for users to install stuff first */ +#ifdef __gnu_linux__ + sys_expandpath("~/.local/lib/pd/extra/", pathbuf, MAXPDSTRING); + STUFF->st_staticpath = namelist_append(0, pathbuf, 0); + sys_expandpath("~/pd-externals", pathbuf, MAXPDSTRING); + STUFF->st_staticpath = namelist_append(STUFF->st_staticpath, pathbuf, 0); + STUFF->st_staticpath = namelist_append(STUFF->st_staticpath, + "/usr/local/lib/pd-externals", 0); +#endif + +#ifdef __APPLE__ + sys_expandpath("~/Library/Pd", pathbuf, MAXPDSTRING); + STUFF->st_staticpath = namelist_append(0, pathbuf, 0); + STUFF->st_staticpath = namelist_append(STUFF->st_staticpath, "/Library/Pd", 0); +#endif + +#ifdef _WIN32 + sys_expandpath("%AppData%/Pd", pathbuf, MAXPDSTRING); + STUFF->st_staticpath = namelist_append(0, pathbuf, 0); + sys_expandpath("%CommonProgramFiles%/Pd", pathbuf, MAXPDSTRING); + STUFF->st_staticpath = namelist_append(STUFF->st_staticpath, pathbuf, 0); +#endif + /* add built-in "extra" path last so its checked last */ + STUFF->st_staticpath = namelist_append(STUFF->st_staticpath, p, 0); +} + + /* try to open a file in the directory "dir", named "name""ext", + for reading. "Name" may have slashes. The directory is copied to + "dirresult" which must be at least "size" bytes. "nameresult" is set + to point to the filename (copied elsewhere into the same buffer). + The "bin" flag requests opening for binary (which only makes a difference + on Windows). */ + +int sys_trytoopenone(const char *dir, const char *name, const char* ext, + char *dirresult, char **nameresult, unsigned int size, int bin) +{ + int fd; + char buf[MAXPDSTRING]; + if (strlen(dir) + strlen(name) + strlen(ext) + 4 > size) + return (-1); + sys_expandpath(dir, buf, MAXPDSTRING); + strcpy(dirresult, buf); + if (*dirresult && dirresult[strlen(dirresult)-1] != '/') + strcat(dirresult, "/"); + strcat(dirresult, name); + strcat(dirresult, ext); + + DEBUG(post("looking for %s",dirresult)); + /* see if we can open the file for reading */ + if ((fd=sys_open(dirresult, O_RDONLY)) >= 0) + { + /* in unix, further check that it's not a directory */ +#ifdef HAVE_UNISTD_H + struct stat statbuf; + int ok = ((fstat(fd, &statbuf) >= 0) && + !S_ISDIR(statbuf.st_mode)); + if (!ok) + { + if (sys_verbose) post("tried %s; stat failed or directory", + dirresult); + close (fd); + fd = -1; + } + else +#endif + { + char *slash; + if (sys_verbose) post("tried %s and succeeded", dirresult); + sys_unbashfilename(dirresult, dirresult); + slash = strrchr(dirresult, '/'); + if (slash) + { + *slash = 0; + *nameresult = slash + 1; + } + else *nameresult = dirresult; + + return (fd); + } + } + else + { + if (sys_verbose) post("tried %s and failed", dirresult); + } + return (-1); +} + + /* check if we were given an absolute pathname, if so try to open it + and return 1 to signal the caller to cancel any path searches */ +int sys_open_absolute(const char *name, const char* ext, + char *dirresult, char **nameresult, unsigned int size, int bin, int *fdp) +{ + if (sys_isabsolutepath(name)) + { + char dirbuf[MAXPDSTRING], *z = strrchr(name, '/'); + int dirlen; + if (!z) + return (0); + dirlen = (int)(z - name); + if (dirlen > MAXPDSTRING-1) + dirlen = MAXPDSTRING-1; + strncpy(dirbuf, name, dirlen); + dirbuf[dirlen] = 0; + *fdp = sys_trytoopenone(dirbuf, name+(dirlen+1), ext, + dirresult, nameresult, size, bin); + return (1); + } + else return (0); +} + +/* search for a file in a specified directory, then along the globally +defined search path, using ext as filename extension. The +fd is returned, the directory ends up in the "dirresult" which must be at +least "size" bytes. "nameresult" is set to point to the filename, which +ends up in the same buffer as dirresult. Exception: +if the 'name' starts with a slash or a letter, colon, and slash in MSW, +there is no search and instead we just try to open the file literally. */ + +/* see also canvas_open() which, in addition, searches down the +canvas-specific path. */ + +static int do_open_via_path(const char *dir, const char *name, + const char *ext, char *dirresult, char **nameresult, unsigned int size, + int bin, t_namelist *searchpath) +{ + t_namelist *nl; + int fd = -1; + + /* first check if "name" is absolute (and if so, try to open) */ + if (sys_open_absolute(name, ext, dirresult, nameresult, size, bin, &fd)) + return (fd); + + /* otherwise "name" is relative; try the directory "dir" first. */ + if ((fd = sys_trytoopenone(dir, name, ext, + dirresult, nameresult, size, bin)) >= 0) + return (fd); + + /* next go through the search path */ + for (nl = searchpath; nl; nl = nl->nl_next) + if ((fd = sys_trytoopenone(nl->nl_string, name, ext, + dirresult, nameresult, size, bin)) >= 0) + return (fd); + + /* next look in built-in paths like "extra" */ + if (sys_usestdpath) + for (nl = STUFF->st_staticpath; nl; nl = nl->nl_next) + if ((fd = sys_trytoopenone(nl->nl_string, name, ext, + dirresult, nameresult, size, bin)) >= 0) + return (fd); + + *dirresult = 0; + *nameresult = dirresult; + return (-1); +} + + /* open via path, using the global search path. */ +int open_via_path(const char *dir, const char *name, const char *ext, + char *dirresult, char **nameresult, unsigned int size, int bin) +{ + return (do_open_via_path(dir, name, ext, dirresult, nameresult, + size, bin, STUFF->st_searchpath)); +} + + /* open a file with a UTF-8 filename + This is needed because WIN32 does not support UTF-8 filenames, only UCS2. + Having this function prevents lots of #ifdefs all over the place. + */ +#ifdef _WIN32 +int sys_open(const char *path, int oflag, ...) +{ + int i, fd; + char pathbuf[MAXPDSTRING]; + wchar_t ucs2path[MAXPDSTRING]; + sys_bashfilename(path, pathbuf); + u8_utf8toucs2(ucs2path, MAXPDSTRING, pathbuf, MAXPDSTRING-1); + /* For the create mode, Win32 does not have the same possibilities, + * so we ignore the argument and just hard-code read/write. */ + if (oflag & O_CREAT) + fd = _wopen(ucs2path, oflag | O_BINARY, _S_IREAD | _S_IWRITE); + else + fd = _wopen(ucs2path, oflag | O_BINARY); + return fd; +} + +FILE *sys_fopen(const char *filename, const char *mode) +{ + char namebuf[MAXPDSTRING]; + wchar_t ucs2buf[MAXPDSTRING]; + wchar_t ucs2mode[MAXPDSTRING]; + sys_bashfilename(filename, namebuf); + u8_utf8toucs2(ucs2buf, MAXPDSTRING, namebuf, MAXPDSTRING-1); + /* mode only uses ASCII, so no need for a full conversion, just copy it */ + mbstowcs(ucs2mode, mode, MAXPDSTRING); + return (_wfopen(ucs2buf, ucs2mode)); +} +#else +#include +int sys_open(const char *path, int oflag, ...) +{ + int i, fd; + char pathbuf[MAXPDSTRING]; + sys_bashfilename(path, pathbuf); + if (oflag & O_CREAT) + { + mode_t mode; + int imode; + va_list ap; + va_start(ap, oflag); + + /* Mac compiler complains if we just set mode = va_arg ... so, even + though we all know it's just an int, we explicitly va_arg to an int + and then convert. + -> http://www.mail-archive.com/bug-gnulib@gnu.org/msg14212.html + -> http://bugs.debian.org/647345 + */ + + imode = va_arg (ap, int); + mode = (mode_t)imode; + va_end(ap); + fd = open(pathbuf, oflag, mode); + } + else + fd = open(pathbuf, oflag); + return fd; +} + +FILE *sys_fopen(const char *filename, const char *mode) +{ + char namebuf[MAXPDSTRING]; + sys_bashfilename(filename, namebuf); + return fopen(namebuf, mode); +} +#endif /* _WIN32 */ + + /* close a previously opened file + this is needed on platforms where you cannot open/close resources + across dll-boundaries, but we provide it for other platforms as well */ +int sys_close(int fd) +{ +#ifdef _WIN32 + return _close(fd); /* Bill Gates is a big fat hen */ +#else + return close(fd); +#endif +} + +int sys_fclose(FILE *stream) +{ + return fclose(stream); +} + + /* Open a help file using the help search path. We expect the ".pd" + suffix here, even though we have to tear it back off for one of the + search attempts. */ +void open_via_helppath(const char *name, const char *dir) +{ + char realname[MAXPDSTRING], dirbuf[MAXPDSTRING], *basename; + /* make up a silly "dir" if none is supplied */ + const char *usedir = (*dir ? dir : "./"); + int fd; + + /* 1. "objectname-help.pd" */ + strncpy(realname, name, MAXPDSTRING-10); + realname[MAXPDSTRING-10] = 0; + if (strlen(realname) > 3 && !strcmp(realname+strlen(realname)-3, ".pd")) + realname[strlen(realname)-3] = 0; + strcat(realname, "-help.pd"); + if ((fd = do_open_via_path(usedir, realname, "", dirbuf, &basename, + MAXPDSTRING, 0, STUFF->st_helppath)) >= 0) + goto gotone; + + /* 2. "help-objectname.pd" */ + strcpy(realname, "help-"); + strncat(realname, name, MAXPDSTRING-10); + realname[MAXPDSTRING-1] = 0; + if ((fd = do_open_via_path(usedir, realname, "", dirbuf, &basename, + MAXPDSTRING, 0, STUFF->st_helppath)) >= 0) + goto gotone; + + post("sorry, couldn't find help patch for \"%s\"", name); + return; +gotone: + close (fd); + glob_evalfile(0, gensym((char*)basename), gensym(dirbuf)); +} + +int sys_argparse(int argc, char **argv); +void sys_doflags( void) +{ + int i, beginstring = 0, state = 0, len; + int rcargc = 0; + char *rcargv[MAXPDSTRING]; + if (!sys_flags) + sys_flags = &s_; + len = (int)strlen(sys_flags->s_name); + if (len > MAXPDSTRING) + { + error("flags: %s: too long", sys_flags->s_name); + return; + } + for (i = 0; i < len+1; i++) + { + int c = sys_flags->s_name[i]; + if (state == 0) + { + if (c && !isspace(c)) + { + beginstring = i; + state = 1; + } + } + else + { + if (!c || isspace(c)) + { + char *foo = malloc(i - beginstring + 1); + if (!foo) + return; + strncpy(foo, sys_flags->s_name + beginstring, i - beginstring); + foo[i - beginstring] = 0; + rcargv[rcargc] = foo; + rcargc++; + if (rcargc >= MAXPDSTRING) + break; + state = 0; + } + } + } + if (sys_argparse(rcargc, rcargv)) + error("error parsing startup arguments"); +} + +/* undo pdtl_encodedialog. This allows dialogs to send spaces, commas, + dollars, and semis down here. */ +t_symbol *sys_decodedialog(t_symbol *s) +{ + char buf[MAXPDSTRING], *sp = s->s_name; + int i; + if (*sp != '+') + bug("sys_decodedialog: %s", sp); + else sp++; + for (i = 0; i < MAXPDSTRING-1; i++, sp++) + { + if (!sp[0]) + break; + if (sp[0] == '+') + { + if (sp[1] == '_') + buf[i] = ' ', sp++; + else if (sp[1] == '+') + buf[i] = '+', sp++; + else if (sp[1] == 'c') + buf[i] = ',', sp++; + else if (sp[1] == 's') + buf[i] = ';', sp++; + else if (sp[1] == 'd') + buf[i] = '$', sp++; + else buf[i] = sp[0]; + } + else buf[i] = sp[0]; + } + buf[i] = 0; + return (gensym(buf)); +} + + /* send the user-specified search path to pd-gui */ +void sys_set_searchpath( void) +{ + int i; + t_namelist *nl; + + sys_gui("set ::tmp_path {}\n"); + for (nl = STUFF->st_searchpath, i = 0; nl; nl = nl->nl_next, i++) + sys_vgui("lappend ::tmp_path {%s}\n", nl->nl_string); + sys_gui("set ::sys_searchpath $::tmp_path\n"); +} + + /* send the hard-coded search path to pd-gui */ +void sys_set_extrapath( void) +{ + int i; + t_namelist *nl; + + sys_gui("set ::tmp_path {}\n"); + for (nl = STUFF->st_staticpath, i = 0; nl; nl = nl->nl_next, i++) + sys_vgui("lappend ::tmp_path {%s}\n", nl->nl_string); + sys_gui("set ::sys_staticpath $::tmp_path\n"); +} + + /* start a search path dialog window */ +void glob_start_path_dialog(t_pd *dummy) +{ + char buf[MAXPDSTRING]; + + sys_set_searchpath(); + sprintf(buf, "pdtk_path_dialog %%s %d %d\n", sys_usestdpath, sys_verbose); + gfxstub_new(&glob_pdobject, (void *)glob_start_path_dialog, buf); +} + + /* new values from dialog window */ +void glob_path_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) +{ + int i; + namelist_free(STUFF->st_searchpath); + STUFF->st_searchpath = 0; + sys_usestdpath = atom_getfloatarg(0, argc, argv); + sys_verbose = atom_getfloatarg(1, argc, argv); + for (i = 0; i < argc-2; i++) + { + t_symbol *s = sys_decodedialog(atom_getsymbolarg(i+2, argc, argv)); + if (*s->s_name) + STUFF->st_searchpath = + namelist_append_files(STUFF->st_searchpath, s->s_name); + } +} + + /* add one item to search path (intended for use by Deken plugin). + if "saveit" is set, also save all settings. */ +void glob_addtopath(t_pd *dummy, t_symbol *path, t_float saveit) +{ + int i; + t_symbol *s = sys_decodedialog(path); + if (*s->s_name) + { + STUFF->st_searchpath = + namelist_append_files(STUFF->st_searchpath, s->s_name); + if (saveit != 0) + sys_savepreferences(0); + } +} + + /* set the global list vars for startup libraries and flags */ +void sys_set_startup( void) +{ + int i; + t_namelist *nl; + + sys_vgui("set ::startup_flags {%s}\n", + (sys_flags? sys_flags->s_name : "")); + sys_gui("set ::startup_libraries {}\n"); + for (nl = STUFF->st_externlist, i = 0; nl; nl = nl->nl_next, i++) + sys_vgui("lappend ::startup_libraries {%s}\n", nl->nl_string); +} + + /* start a startup dialog window */ +void glob_start_startup_dialog(t_pd *dummy) +{ + char buf[MAXPDSTRING]; + + sys_set_startup(); + sprintf(buf, "pdtk_startup_dialog %%s %d \"%s\"\n", sys_defeatrt, + (sys_flags? sys_flags->s_name : "")); + gfxstub_new(&glob_pdobject, (void *)glob_start_startup_dialog, buf); +} + + /* new values from dialog window */ +void glob_startup_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) +{ + int i; + namelist_free(STUFF->st_externlist); + STUFF->st_externlist = 0; + sys_defeatrt = atom_getfloatarg(0, argc, argv); + sys_flags = sys_decodedialog(atom_getsymbolarg(1, argc, argv)); + for (i = 0; i < argc-2; i++) + { + t_symbol *s = sys_decodedialog(atom_getsymbolarg(i+2, argc, argv)); + if (*s->s_name) + STUFF->st_externlist = + namelist_append_files(STUFF->st_externlist, s->s_name); + } +} + + diff --git a/ports/camomile/source/LibPd/pure-data/src/s_print.c b/ports/camomile/source/LibPd/pure-data/src/s_print.c new file mode 100644 index 00000000..866c7c6f --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_print.c @@ -0,0 +1,316 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include +#include +#include +#include +#include +#include "s_stuff.h" + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +t_printhook sys_printhook; +int sys_printtostderr; + +/* escape characters for tcl/tk */ +static char* strnescape(char *dest, const char *src, size_t len) +{ + int ptin = 0; + unsigned ptout = 0; + for(; ptout < len; ptin++, ptout++) + { + int c = src[ptin]; + if (c == '\\' || c == '{' || c == '}') + dest[ptout++] = '\\'; + dest[ptout] = src[ptin]; + if (c==0) break; + } + + if(ptout < len) + dest[ptout]=0; + else + dest[len-1]=0; + + return dest; +} + +static char* strnpointerid(char *dest, const void *pointer, size_t len) +{ + *dest=0; + if (pointer) + snprintf(dest, len, ".x%lx", (unsigned long)pointer); + return dest; +} + +static void dopost(const char *s) +{ + if (sys_printhook) + (*sys_printhook)(s); + else if (sys_printtostderr || !sys_havegui()) +#ifdef _WIN32 + fwprintf(stderr, L"%S", s); +#else + fprintf(stderr, "%s", s); +#endif + else + { + char upbuf[MAXPDSTRING]; + sys_vgui("::pdwindow::post {%s}\n", strnescape(upbuf, s, MAXPDSTRING)); + } +} + +static void doerror(const void *object, const char *s) +{ + char upbuf[MAXPDSTRING]; + upbuf[MAXPDSTRING-1]=0; + + // what about sys_printhook_error ? + if (sys_printhook) + { + snprintf(upbuf, MAXPDSTRING-1, "error: %s", s); + (*sys_printhook)(upbuf); + } + else if (sys_printtostderr) + fprintf(stderr, "error: %s", s); + else + { + char obuf[MAXPDSTRING]; + sys_vgui("::pdwindow::logpost {%s} 1 {%s}\n", + strnpointerid(obuf, object, MAXPDSTRING), + strnescape(upbuf, s, MAXPDSTRING)); + } +} + +static void dologpost(const void *object, const int level, const char *s) +{ + char upbuf[MAXPDSTRING]; + upbuf[MAXPDSTRING-1]=0; + + // what about sys_printhook_verbose ? + if (sys_printhook) + { + snprintf(upbuf, MAXPDSTRING-1, "verbose(%d): %s", level, s); + (*sys_printhook)(upbuf); + } + else if (sys_printtostderr) + { + fprintf(stderr, "verbose(%d): %s", level, s); + } + else + { + char obuf[MAXPDSTRING]; + sys_vgui("::pdwindow::logpost {%s} %d {%s}\n", + strnpointerid(obuf, object, MAXPDSTRING), + level, strnescape(upbuf, s, MAXPDSTRING)); + } +} + +void logpost(const void *object, const int level, const char *fmt, ...) +{ + char buf[MAXPDSTRING]; + va_list ap; + t_int arg[8]; + int i; + va_start(ap, fmt); + vsnprintf(buf, MAXPDSTRING-1, fmt, ap); + va_end(ap); + strcat(buf, "\n"); + + dologpost(object, level, buf); +} + +void post(const char *fmt, ...) +{ + char buf[MAXPDSTRING]; + va_list ap; + t_int arg[8]; + int i; + va_start(ap, fmt); + vsnprintf(buf, MAXPDSTRING-1, fmt, ap); + va_end(ap); + strcat(buf, "\n"); + + dopost(buf); +} + +void startpost(const char *fmt, ...) +{ + char buf[MAXPDSTRING]; + va_list ap; + t_int arg[8]; + int i; + va_start(ap, fmt); + vsnprintf(buf, MAXPDSTRING-1, fmt, ap); + va_end(ap); + + dopost(buf); +} + +void poststring(const char *s) +{ + dopost(" "); + + dopost(s); +} + +void postatom(int argc, t_atom *argv) +{ + int i; + for (i = 0; i < argc; i++) + { + char buf[MAXPDSTRING]; + atom_string(argv+i, buf, MAXPDSTRING); + poststring(buf); + } +} + +void postfloat(t_float f) +{ + char buf[80]; + t_atom a; + SETFLOAT(&a, f); + + postatom(1, &a); +} + +void endpost(void) +{ + if (sys_printhook) + (*sys_printhook)("\n"); + else if (sys_printtostderr) + fprintf(stderr, "\n"); + else post(""); +} + +void error(const char *fmt, ...) +{ + char buf[MAXPDSTRING]; + va_list ap; + t_int arg[8]; + int i; + + va_start(ap, fmt); + vsnprintf(buf, MAXPDSTRING-1, fmt, ap); + va_end(ap); + strcat(buf, "\n"); + + doerror(NULL, buf); +} + +void verbose(int level, const char *fmt, ...) +{ + char buf[MAXPDSTRING]; + va_list ap; + t_int arg[8]; + int i; + int loglevel=level+3; + + if(level>sys_verbose)return; + + va_start(ap, fmt); + vsnprintf(buf, MAXPDSTRING-1, fmt, ap); + va_end(ap); + strcat(buf, "\n"); + + dologpost(NULL, loglevel, buf); +} + + /* here's the good way to log errors -- keep a pointer to the + offending or offended object around so the user can search for it + later. */ + +static void *error_object; +static char error_string[256]; +void canvas_finderror(void *object); + +void pd_error(void *object, const char *fmt, ...) +{ + char buf[MAXPDSTRING]; + va_list ap; + t_int arg[8]; + int i; + static int saidit; + + va_start(ap, fmt); + vsnprintf(buf, MAXPDSTRING-1, fmt, ap); + va_end(ap); + strcat(buf, "\n"); + + doerror(object, buf); + + error_object = object; + strncpy(error_string, buf, 256); + error_string[255] = 0; + + if (!saidit) + { + logpost(NULL, 4, + "... you might be able to track this down from the Find menu."); + saidit = 1; + } +} + +void glob_finderror(t_pd *dummy) +{ + if (!error_object) + post("no findable error yet"); + else + { + post("last trackable error:"); + post("%s", error_string); + canvas_finderror(error_object); + } +} + +void glob_findinstance(t_pd *dummy, t_symbol*s) +{ + // revert s to (potential) pointer to object + PD_LONGINTTYPE obj = 0; + if (sscanf(s->s_name, ".x%lx", &obj)) + { + if (obj) + { + canvas_finderror((void *)obj); + } + } +} + +void bug(const char *fmt, ...) +{ + char buf[MAXPDSTRING]; + va_list ap; + t_int arg[8]; + int i; + va_start(ap, fmt); + vsnprintf(buf, MAXPDSTRING-1, fmt, ap); + va_end(ap); + + error("consistency check failed: %s", buf); +} + + /* this isn't worked out yet. */ +static const char *errobject; +static const char *errstring; + +void sys_logerror(const char *object, const char *s) +{ + errobject = object; + errstring = s; +} + +void sys_unixerror(const char *object) +{ + errobject = object; + errstring = strerror(errno); +} + +void sys_ouch(void) +{ + if (*errobject) error("%s: %s", errobject, errstring); + else error("%s", errstring); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/s_stuff.h b/ports/camomile/source/LibPd/pure-data/src/s_stuff.h new file mode 100644 index 00000000..5b5df8d1 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_stuff.h @@ -0,0 +1,416 @@ +#pragma once +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* Audio and MIDI I/O, and other scheduling and system stuff. */ + +/* NOTE: this file describes Pd implementation details which may change +in future releases. The public (stable) API is in m_pd.h. */ + +/* in s_path.c */ + +typedef struct _namelist /* element in a linked list of stored strings */ +{ + struct _namelist *nl_next; /* next in list */ + char *nl_string; /* the string */ +} t_namelist; + +t_namelist *namelist_append(t_namelist *listwas, const char *s, int allowdup); +EXTERN t_namelist *namelist_append_files(t_namelist *listwas, const char *s); +void namelist_free(t_namelist *listwas); +char *namelist_get(t_namelist *namelist, int n); +void sys_setextrapath(const char *p); +extern int sys_usestdpath; +int sys_open_absolute(const char *name, const char* ext, + char *dirresult, char **nameresult, unsigned int size, int bin, int *fdp); +int sys_trytoopenone(const char *dir, const char *name, const char* ext, + char *dirresult, char **nameresult, unsigned int size, int bin); +t_symbol *sys_decodedialog(t_symbol *s); + +/* s_file.c */ + +void sys_loadpreferences(const char *filename, int startingup); +void sys_savepreferences(const char *filename); +extern int sys_defeatrt; +extern t_symbol *sys_flags; + +/* s_main.c */ +extern int sys_debuglevel; +extern int sys_verbose; +extern int sys_noloadbang; +EXTERN int sys_havegui( void); +extern char *sys_guicmd; + +EXTERN int sys_nearestfontsize(int fontsize); + +extern int sys_defaultfont; +EXTERN t_symbol *sys_libdir; /* library directory for auxilliary files */ +extern t_symbol *sys_guidir; /* directory holding pd_gui, u_pdsend, etc */ + +/* s_loader.c */ + +typedef int (*loader_t)(t_canvas *canvas, const char *classname, const char*path); /* callback type */ +EXTERN int sys_load_lib(t_canvas *canvas, const char *classname); +EXTERN void sys_register_loader(loader_t loader); + +/* s_audio.c */ + +#define SENDDACS_NO 0 /* return values for sys_send_dacs() */ +#define SENDDACS_YES 1 +#define SENDDACS_SLEPT 2 + +#define DEFDACBLKSIZE 64 +extern int sys_hipriority; /* real-time flag, true if priority boosted */ +extern int sys_schedadvance; +extern int sys_sleepgrain; +extern int sys_advance_samples; /* scheduler advance in samples */ +EXTERN void sys_set_audio_settings(int naudioindev, int *audioindev, + int nchindev, int *chindev, + int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev, + int srate, int advance, int callback, int blocksize); +/* the same as above, but reopens the audio subsystem if needed */ +EXTERN void sys_set_audio_settings_reopen(int naudioindev, int *audioindev, + int nchindev, int *chindev, + int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev, + int srate, int advance, int callback, int blocksize); +EXTERN void sys_reopen_audio( void); +EXTERN void sys_close_audio(void); + /* return true if the interface prefers always being open (ala jack) : */ +EXTERN int audio_shouldkeepopen( void); +EXTERN int audio_isopen( void); /* true if audio interface is open */ +EXTERN int sys_audiodevnametonumber(int output, const char *name); +EXTERN void sys_audiodevnumbertoname(int output, int devno, char *name, + int namesize); + +int sys_send_dacs(void); +void sys_reportidle(void); +void sys_set_priority(int higher); +void sys_audiobuf(int nbufs); +void sys_getmeters(t_sample *inmax, t_sample *outmax); +void sys_listdevs(void); +void sys_setblocksize(int n); + +EXTERN void sys_get_audio_devs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, int *cancallback, + int maxndev, int devdescsize); +EXTERN void sys_get_audio_apis(char *buf); + +/* s_midi.c */ +#define MAXMIDIINDEV 16 /* max. number of input ports */ +#define MAXMIDIOUTDEV 16 /* max. number of output ports */ +extern int sys_midiapi; +extern int sys_nmidiin; +extern int sys_nmidiout; +extern int sys_midiindevlist[]; +extern int sys_midioutdevlist[]; + +EXTERN void sys_open_midi(int nmidiin, int *midiinvec, + int nmidiout, int *midioutvec, int enable); + +EXTERN void sys_get_midi_apis(char *buf); +EXTERN void sys_get_midi_devs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, + int maxndev, int devdescsize); +EXTERN void sys_get_midi_params(int *pnmidiindev, int *pmidiindev, + int *pnmidioutdev, int *pmidioutdev); +EXTERN int sys_mididevnametonumber(int output, const char *name); +EXTERN void sys_mididevnumbertoname(int output, int devno, char *name, + int namesize); + +EXTERN void sys_reopen_midi( void); +EXTERN void sys_close_midi( void); +EXTERN void sys_putmidimess(int portno, int a, int b, int c); +EXTERN void sys_putmidibyte(int portno, int a); +EXTERN void sys_poll_midi(void); +EXTERN void sys_setmiditimediff(double inbuftime, double outbuftime); +EXTERN void sys_midibytein(int portno, int byte); + + /* implemented in the system dependent MIDI code (s_midi_pm.c, etc. ) */ +void midi_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int maxndev, int devdescsize); +void sys_do_open_midi(int nmidiindev, int *midiindev, + int nmidioutdev, int *midioutdev); + +#ifdef USEAPI_ALSA +EXTERN void sys_alsa_putmidimess(int portno, int a, int b, int c); +EXTERN void sys_alsa_putmidibyte(int portno, int a); +EXTERN void sys_alsa_poll_midi(void); +EXTERN void sys_alsa_setmiditimediff(double inbuftime, double outbuftime); +EXTERN void sys_alsa_midibytein(int portno, int byte); +EXTERN void sys_alsa_close_midi( void); + + + /* implemented in the system dependent MIDI code (s_midi_pm.c, etc. ) */ +void midi_alsa_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int maxndev, int devdescsize); +void sys_alsa_do_open_midi(int nmidiindev, int *midiindev, + int nmidioutdev, int *midioutdev); +#endif + +/* m_sched.c */ +EXTERN void sys_log_error(int type); +#define ERR_NOTHING 0 +#define ERR_ADCSLEPT 1 +#define ERR_DACSLEPT 2 +#define ERR_RESYNC 3 +#define ERR_DATALATE 4 + +#define SCHED_AUDIO_NONE 0 +#define SCHED_AUDIO_POLL 1 +#define SCHED_AUDIO_CALLBACK 2 +void sched_set_using_audio(int flag); + +/* s_inter.c */ + +EXTERN void sys_microsleep(int microsec); +EXTERN void sys_init_fdpoll(void); + +EXTERN void sys_bail(int exitcode); +EXTERN int sys_pollgui(void); + +EXTERN_STRUCT _socketreceiver; +#define t_socketreceiver struct _socketreceiver + +typedef void (*t_socketnotifier)(void *x, int n); +typedef void (*t_socketreceivefn)(void *x, t_binbuf *b); + +EXTERN t_socketreceiver *socketreceiver_new(void *owner, + t_socketnotifier notifier, t_socketreceivefn socketreceivefn, int udp); +EXTERN void socketreceiver_read(t_socketreceiver *x, int fd); +EXTERN void sys_sockerror(char *s); +EXTERN void sys_closesocket(int fd); + +typedef void (*t_fdpollfn)(void *ptr, int fd); +EXTERN void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr); +EXTERN void sys_rmpollfn(int fd); +#if defined(USEAPI_OSS) || defined(USEAPI_ALSA) +void sys_setalarm(int microsec); +#endif + +#define API_NONE 0 +#define API_ALSA 1 +#define API_OSS 2 +#define API_MMIO 3 +#define API_PORTAUDIO 4 +#define API_JACK 5 +#define API_SGI 6 /* gone */ +#define API_AUDIOUNIT 7 +#define API_ESD 8 /* no idea what this was, probably gone now */ +#define API_DUMMY 9 + + /* figure out which API should be the default. The one we judge most + likely to offer a working device takes precedence so that if you + start up Pd for the first time there's a reasonable chance you'll have + sound. (You'd think portaudio would be best but it seems to default + to jack on linux, and and on Windows we only use it for ASIO). + If nobody shows up, define DUMMY and make it the default.*/ +#if defined(USEAPI_MMIO) +# define API_DEFAULT API_MMIO +# define API_DEFSTRING "MMIO" +#elif defined(USEAPI_ALSA) +# define API_DEFAULT API_ALSA +# define API_DEFSTRING "ALSA" +#elif defined(USEAPI_OSS) +# define API_DEFAULT API_OSS +# define API_DEFSTRING "OSS" +#elif defined(USEAPI_AUDIOUNIT) +# define API_DEFAULT API_AUDIOUNIT +# define API_DEFSTRING "AudioUnit" +#elif defined(USEAPI_ESD) +# define API_DEFAULT API_ESD +# define API_DEFSTRING "ESD (?)" +#elif defined(USEAPI_PORTAUDIO) +# define API_DEFAULT API_PORTAUDIO +# define API_DEFSTRING "portaudio" +#elif defined(USEAPI_JACK) +# define API_DEFAULT API_JACK +# define API_DEFSTRING "Jack audio connection kit" +#else +# ifndef USEAPI_DUMMY /* we need at least one so bring in the dummy */ +# define USEAPI_DUMMY +# endif /* USEAPI_DUMMY */ +# define API_DEFAULT API_DUMMY +# define API_DEFSTRING "dummy audio" +#endif + +#define DEFAULTAUDIODEV 0 + +#define MAXAUDIOINDEV 4 +#define MAXAUDIOOUTDEV 4 + +#define DEFMIDIDEV 0 + +#define DEFAULTSRATE 44100 +#ifdef _WIN32 +#define DEFAULTADVANCE 80 +#else +#ifdef __APPLE__ +#define DEFAULTADVANCE 5 /* this is in addition to their own delay */ +#else +#define DEFAULTADVANCE 25 +#endif +#endif + +typedef void (*t_audiocallback)(void); + +int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin, + t_sample *soundout, int framesperbuf, int nbuffers, + int indeviceno, int outdeviceno, t_audiocallback callback); +void pa_close_audio(void); +int pa_send_dacs(void); +void pa_listdevs(void); +void pa_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); + +int oss_open_audio(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate, int blocksize); +void oss_close_audio(void); +int oss_send_dacs(void); +void oss_reportidle(void); +void oss_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); + +int alsa_open_audio(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate, int blocksize); +void alsa_close_audio(void); +int alsa_send_dacs(void); +void alsa_reportidle(void); +void alsa_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); + +int jack_open_audio(int wantinchans, int wantoutchans, int srate, + t_audiocallback callback); +void jack_close_audio(void); +int jack_send_dacs(void); +void jack_reportidle(void); +void jack_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); +void jack_listdevs(void); +void jack_client_name(char *name); +void jack_autoconnect(int); + +int mmio_open_audio(int naudioindev, int *audioindev, + int nchindev, int *chindev, int naudiooutdev, int *audiooutdev, + int nchoutdev, int *choutdev, int rate, int blocksize); +void mmio_close_audio( void); +void mmio_reportidle(void); +int mmio_send_dacs(void); +void mmio_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); + +int audiounit_open_audio(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate); +void audiounit_close_audio(void); +int audiounit_send_dacs(void); +void audiounit_listdevs(void); +void audiounit_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); + +int esd_open_audio(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate); +void esd_close_audio(void); +int esd_send_dacs(void); +void esd_listdevs(void); +void esd_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); + +int dummy_open_audio(int nin, int nout, int sr); +int dummy_close_audio( void); +int dummy_send_dacs( void); +void dummy_getdevs(char *indevlist, int *nindevs, char *outdevlist, + int *noutdevs, int *canmulti, int maxndev, int devdescsize); +void dummy_listdevs( void); + +void sys_listmididevs(void); +EXTERN void sys_set_midi_api(int whichapi); +EXTERN void sys_set_audio_api(int whichapi); +EXTERN int sys_audioapi; +EXTERN void sys_set_audio_state(int onoff); + +/* API dependent audio flags and settings */ +void oss_set32bit( void); +void linux_alsa_devname(char *devname); + +EXTERN void sys_get_audio_params( + int *pnaudioindev, int *paudioindev, int *chindev, + int *pnaudiooutdev, int *paudiooutdev, int *choutdev, + int *prate, int *padvance, int *callback, int *blocksize); +void sys_save_audio_params( + int naudioindev, int *audioindev, int *chindev, + int naudiooutdev, int *audiooutdev, int *choutdev, + int rate, int advance, int callback, int blocksize); + +/* s_file.c */ + +typedef void (*t_printhook)(const char *s); +extern t_printhook sys_printhook; /* set this to override printing */ +extern int sys_printtostderr; + +/* jsarlo { */ + +EXTERN int sys_externalschedlib; + +EXTERN t_sample* get_sys_soundout(void ) ; +EXTERN t_sample* get_sys_soundin(void ) ; +EXTERN int* get_sys_main_advance(void ) ; +EXTERN double* get_sys_time_per_dsp_tick(void ) ; +EXTERN int* get_sys_schedblocksize(void ) ; +EXTERN double* get_sys_time(void ) ; +EXTERN t_float* get_sys_dacsr(void ) ; +EXTERN int* get_sys_sleepgrain(void ) ; +EXTERN int* get_sys_schedadvance(void ) ; + +EXTERN void sys_clearhist(void ); +EXTERN void sys_initmidiqueue(void ); +EXTERN int sys_addhist(int phase); +EXTERN void sched_tick( void); +EXTERN void sys_pollmidiqueue(void ); +EXTERN void sys_setchsr(int chin, int chout, int sr); + +EXTERN void inmidi_realtimein(int portno, int cmd); +EXTERN void inmidi_byte(int portno, int byte); +EXTERN void inmidi_sysex(int portno, int byte); +EXTERN void inmidi_noteon(int portno, int channel, int pitch, int velo); +EXTERN void inmidi_controlchange(int portno, + int channel, + int ctlnumber, + int value); +EXTERN void inmidi_programchange(int portno, int channel, int value); +EXTERN void inmidi_pitchbend(int portno, int channel, int value); +EXTERN void inmidi_aftertouch(int portno, int channel, int value); +EXTERN void inmidi_polyaftertouch(int portno, + int channel, + int pitch, + int value); +/* } jsarlo */ +EXTERN int sys_zoom_open; + +struct _instancestuff +{ + t_namelist *st_externlist; + t_namelist *st_searchpath; + t_namelist *st_staticpath; + t_namelist *st_helppath; + int st_schedblocksize; /* audio block size for scheduler */ + int st_blocksize; /* audio I/O block size in sample frames */ + t_float st_dacsr; /* I/O sample rate */ + int st_inchannels; + int st_outchannels; + t_sample *st_soundout; + t_sample *st_soundin; + double st_time_per_dsp_tick; /* obsolete - included for GEM?? */ +}; + +#define STUFF (pd_this->pd_stuff) diff --git a/ports/camomile/source/LibPd/pure-data/src/s_utf8.c b/ports/camomile/source/LibPd/pure-data/src/s_utf8.c new file mode 100644 index 00000000..6bc8e230 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_utf8.c @@ -0,0 +1,282 @@ +/* + Basic UTF-8 manipulation routines + by Jeff Bezanson + placed in the public domain Fall 2005 + + This code is designed to provide the utilities you need to manipulate + UTF-8 as an internal string encoding. These functions do not perform the + error checking normally needed when handling UTF-8 data, so if you happen + to be from the Unicode Consortium you will want to flay me alive. + I do this because error checking can be performed at the boundaries (I/O), + with these routines reserved for higher performance on data known to be + valid. + + modified by Bryan Jurish (moo) March 2009 + + removed some unneeded functions (escapes, printf etc), added others +*/ +#include +#include +#include +#include +#ifdef _WIN32 +# include /* MSVC or mingw on windows */ +#elif defined(__linux__) || defined(__APPLE__) +# include /* linux, mac, mingw, cygwin */ +#else +# include /* BSDs for example */ +#endif + +#include "s_utf8.h" + +static const uint32_t offsetsFromUTF8[6] = { + 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL +}; + +static const char trailingBytesForUTF8[256] = { + 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,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,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,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,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,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + + +/* returns length of next utf-8 sequence */ +int u8_seqlen(char *s) +{ + return trailingBytesForUTF8[(unsigned int)(unsigned char)s[0]] + 1; +} + +/* conversions without error checking + only works for valid UTF-8, i.e. no 5- or 6-byte sequences + srcsz = source size in bytes, or -1 if 0-terminated + sz = dest size in # of wide characters + + returns # characters converted + dest will always be L'\0'-terminated, even if there isn't enough room + for all the characters. + if sz = srcsz+1 (i.e. 4*srcsz+4 bytes), there will always be enough space. +*/ +int u8_utf8toucs2(uint16_t *dest, int sz, char *src, int srcsz) +{ + uint16_t ch; + char *src_end = src + srcsz; + int nb; + int i=0; + + while (i < sz-1) { + nb = trailingBytesForUTF8[(unsigned char)*src]; + if (srcsz == -1) { + if (*src == 0) + goto done_toucs; + } + else { + if (src + nb >= src_end) + goto done_toucs; + } + ch = 0; + switch (nb) { + /* these fall through deliberately */ + case 3: ch += (unsigned char)*src++; ch <<= 6; + case 2: ch += (unsigned char)*src++; ch <<= 6; + case 1: ch += (unsigned char)*src++; ch <<= 6; + case 0: ch += (unsigned char)*src++; + } + ch -= offsetsFromUTF8[nb]; + dest[i++] = ch; + } + done_toucs: + dest[i] = 0; + return i; +} + +/* srcsz = number of source characters, or -1 if 0-terminated + sz = size of dest buffer in bytes + + returns # characters converted + dest will only be '\0'-terminated if there is enough space. this is + for consistency; imagine there are 2 bytes of space left, but the next + character requires 3 bytes. in this case we could NUL-terminate, but in + general we can't when there's insufficient space. therefore this function + only NUL-terminates if all the characters fit, and there's space for + the NUL as well. + the destination string will never be bigger than the source string. +*/ +int u8_ucs2toutf8(char *dest, int sz, uint16_t *src, int srcsz) +{ + uint16_t ch; + int i = 0; + char *dest_end = dest + sz; + + while (srcsz<0 ? src[i]!=0 : i < srcsz) { + ch = src[i]; + if (ch < 0x80) { + if (dest >= dest_end) + return i; + *dest++ = (char)ch; + } + else if (ch < 0x800) { + if (dest >= dest_end-1) + return i; + *dest++ = (ch>>6) | 0xC0; + *dest++ = (ch & 0x3F) | 0x80; + } + else { + if (dest >= dest_end-2) + return i; + *dest++ = (ch>>12) | 0xE0; + *dest++ = ((ch>>6) & 0x3F) | 0x80; + *dest++ = (ch & 0x3F) | 0x80; + } + i++; + } + if (dest < dest_end) + *dest = '\0'; + return i; +} + +/* moo: get byte length of character number, or 0 if not supported */ +int u8_wc_nbytes(uint32_t ch) +{ + if (ch < 0x80) return 1; + if (ch < 0x800) return 2; + if (ch < 0x10000) return 3; + if (ch < 0x200000) return 4; + return 0; /*-- bad input --*/ +} + +int u8_wc_toutf8(char *dest, uint32_t ch) +{ + if (ch < 0x80) { + dest[0] = (char)ch; + return 1; + } + if (ch < 0x800) { + dest[0] = (ch>>6) | 0xC0; + dest[1] = (ch & 0x3F) | 0x80; + return 2; + } + if (ch < 0x10000) { + dest[0] = (ch>>12) | 0xE0; + dest[1] = ((ch>>6) & 0x3F) | 0x80; + dest[2] = (ch & 0x3F) | 0x80; + return 3; + } + if (ch < 0x110000) { + dest[0] = (ch>>18) | 0xF0; + dest[1] = ((ch>>12) & 0x3F) | 0x80; + dest[2] = ((ch>>6) & 0x3F) | 0x80; + dest[3] = (ch & 0x3F) | 0x80; + return 4; + } + return 0; +} + +/*-- moo --*/ +int u8_wc_toutf8_nul(char *dest, uint32_t ch) +{ + int sz = u8_wc_toutf8(dest,ch); + dest[sz] = '\0'; + return sz; +} + +/* charnum => byte offset */ +int u8_offset(char *str, int charnum) +{ + char *string = str; + + while (charnum > 0 && *string != '\0') { + if (*string++ & 0x80) { + if (!isutf(*string)) { + ++string; + if (!isutf(*string)) { + ++string; + if (!isutf(*string)) { + ++string; + } + } + } + } + --charnum; + } + + return (int)(string - str); +} + +/* byte offset => charnum */ +int u8_charnum(char *s, int offset) +{ + int charnum = 0; + char *string = s; + char *const end = string + offset; + + while (string < end && *string != '\0') { + if (*string++ & 0x80) { + if (!isutf(*string)) { + ++string; + if (!isutf(*string)) { + ++string; + if (!isutf(*string)) { + ++string; + } + } + } + } + ++charnum; + } + return charnum; +} + +/* reads the next utf-8 sequence out of a string, updating an index */ +uint32_t u8_nextchar(char *s, int *i) +{ + uint32_t ch = 0; + int sz = 0; + + do { + ch <<= 6; + ch += (unsigned char)s[(*i)++]; + sz++; + } while (s[*i] && !isutf(s[*i])); + ch -= offsetsFromUTF8[sz-1]; + + return ch; +} + +/* number of characters */ +int u8_strlen(char *s) +{ + int count = 0; + int i = 0; + + while (u8_nextchar(s, &i) != 0) + count++; + + return count; +} + +void u8_inc(char *s, int *i) +{ + if (s[(*i)++] & 0x80) { + if (!isutf(s[*i])) { + ++(*i); + if (!isutf(s[*i])) { + ++(*i); + if (!isutf(s[*i])) { + ++(*i); + } + } + } + } +} + +void u8_dec(char *s, int *i) +{ + (void)(isutf(s[--(*i)]) || isutf(s[--(*i)]) || + isutf(s[--(*i)]) || --(*i)); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/s_utf8.h b/ports/camomile/source/LibPd/pure-data/src/s_utf8.h new file mode 100644 index 00000000..c8969e8b --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_utf8.h @@ -0,0 +1,85 @@ +#ifndef S_UTF8_H +#define S_UTF8_H + +#include "m_pd.h" + +#ifndef UCS4 +# define UCS4 uint32_t +#endif + +/* UTF8_SUPPORT_FULL_UCS4 + * define this to support the full potential range of UCS-4 codepoints + * (in anticipation of a future UTF-8 standard) + */ +/*#define UTF8_SUPPORT_FULL_UCS4 1*/ +#undef UTF8_SUPPORT_FULL_UCS4 + +/* UTF8_MAXBYTES + * maximum number of bytes required to represent a single character in UTF-8 + * + * UTF8_MAXBYTES1 = UTF8_MAXBYTES+1 + * maximum bytes per character including NUL terminator + */ +#ifdef UTF8_SUPPORT_FULL_UCS4 +# ifndef UTF8_MAXBYTES +# define UTF8_MAXBYTES 6 +# endif +# ifndef UTF8_MAXBYTES1 +# define UTF8_MAXBYTES1 7 +# endif +#else +# ifndef UTF8_MAXBYTES +# define UTF8_MAXBYTES 4 +# endif +# ifndef UTF8_MAXBYTES1 +# define UTF8_MAXBYTES1 5 +# endif +#endif +/*--/moo--*/ + +/* is c the start of a utf8 sequence? */ +#define isutf(c) (((c)&0xC0)!=0x80) + +/* convert UTF-8 data to UCS-2 wide character */ +int u8_utf8toucs2(uint16_t *dest, int sz, char *src, int srcsz); + +/* the opposite conversion */ +int u8_ucs2toutf8(char *dest, int sz, uint16_t *src, int srcsz); + +/* moo: get byte length of character number, or 0 if not supported */ +int u8_wc_nbytes(uint32_t ch); + +/* moo: compute required storage for UTF-8 encoding of 's[0..n-1]' */ +int u8_wcs_nbytes(uint32_t *ucs, int size); + +/* single character to UTF-8, no NUL termination */ +int u8_wc_toutf8(char *dest, uint32_t ch); + +/* moo: single character to UTF-8, with NUL termination */ +int u8_wc_toutf8_nul(char *dest, uint32_t ch); + +/* character number to byte offset */ +int u8_offset(char *str, int charnum); + +/* byte offset to character number */ +int u8_charnum(char *s, int offset); + +/* return next character, updating an index variable */ +uint32_t u8_nextchar(char *s, int *i); + +/* move to next character */ +void u8_inc(char *s, int *i); + +/* move to previous character */ +void u8_dec(char *s, int *i); + +/* moo: move pointer to next character */ +void u8_inc_ptr(char **sp); + +/* moo: move pointer to previous character */ +void u8_dec_ptr(char **sp); + +/* returns length of next utf-8 sequence */ +int u8_seqlen(char *s); + +#endif /* S_UTF8_H */ diff --git a/ports/camomile/source/LibPd/pure-data/src/s_watchdog.c b/ports/camomile/source/LibPd/pure-data/src/s_watchdog.c new file mode 100644 index 00000000..75fb7143 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/s_watchdog.c @@ -0,0 +1,51 @@ +/* Copyright (c) 1997-2000 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This file is compiled into the separate program, "pd-watchdog," which +tries to prevent Pd from locking up the processor if it's at realtime +priority. Linux only. Invoked from s_inter.c. */ + +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int happy = 1; + while (1) + { + struct timeval timout; + fd_set readset, exceptset; + if (happy) + { + timout.tv_sec = 5; + timout.tv_usec = 0; + } + else + { + timout.tv_sec = 2; + timout.tv_usec = 0; + } + FD_ZERO(&readset); + FD_SET(0, &readset); + FD_ZERO(&exceptset); + FD_SET(0, &exceptset); + select(1, &readset, 0, &exceptset, &timout); + if (FD_ISSET(0, &exceptset)) + return (0); + if (FD_ISSET(0, &readset)) + { + char buf[100]; + happy = 1; + if (read(0, &buf, 100) <= 0) + return (0); + else continue; + } + happy = 0; + kill(getppid(), SIGHUP); + fprintf(stderr, "watchdog: signaling pd...\n"); + } +} diff --git a/ports/camomile/source/LibPd/pure-data/src/u_pdreceive.c b/ports/camomile/source/LibPd/pure-data/src/u_pdreceive.c new file mode 100644 index 00000000..1b9431d3 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/u_pdreceive.c @@ -0,0 +1,306 @@ +/* Copyright (c) 2000 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in the Pd distribution. */ + +/* the "pdreceive" command. This is a standalone program that receives messages +from Pd via the netsend/netreceive ("FUDI") protocol, and copies them to +standard output. */ + +/* May 2008 : fixed a buffer overflow problem; pdreceive sometimes + repeated infinitely its buffer during high speed transfer. + Moonix::Antoine Rousseau +*/ + +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include +#else +#include +#include +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#endif + +typedef struct _fdpoll +{ + int fdp_fd; + char *fdp_outbuf;/*output message buffer*/ + int fdp_outlen; /*length of output message*/ + int fdp_discard;/*buffer overflow: output message is incomplete, discard it*/ + int fdp_gotsemi;/*last char from input was a semicolon*/ +} t_fdpoll; + +static int nfdpoll; +static t_fdpoll *fdpoll; +static int maxfd; +static int sockfd; +static int protocol; + +static void sockerror(char *s); +static void x_closesocket(int fd); +static void dopoll(void); +#define BUFSIZE 4096 + +int main(int argc, char **argv) +{ + int portno; + struct sockaddr_in server = {0}; + int nretry = 10; +#ifdef _WIN32 + short version = MAKEWORD(2, 0); + WSADATA nobby; +#endif + if (argc < 2 || sscanf(argv[1], "%d", &portno) < 1 || portno <= 0) + goto usage; + if (argc >= 3) + { + if (!strcmp(argv[2], "tcp")) + protocol = SOCK_STREAM; + else if (!strcmp(argv[2], "udp")) + protocol = SOCK_DGRAM; + else goto usage; + } + else protocol = SOCK_STREAM; +#ifdef _WIN32 + if (WSAStartup(version, &nobby)) sockerror("WSAstartup"); +#endif + sockfd = socket(AF_INET, protocol, 0); + if (sockfd < 0) + { + sockerror("socket()"); + exit(1); + } + maxfd = sockfd + 1; + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + + /* assign client port number */ + server.sin_port = htons((unsigned short)portno); + + /* name the socket */ + if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) + { + sockerror("bind"); + x_closesocket(sockfd); + return (0); + } + if (protocol == SOCK_STREAM) + { + if (listen(sockfd, 5) < 0) + { + sockerror("listen"); + x_closesocket(sockfd); + exit(1); + } + } + /* now loop forever selecting on sockets */ + while (1) + dopoll(); + +usage: + fprintf(stderr, "usage: pdreceive [udp|tcp]\n"); + fprintf(stderr, "(default is tcp)\n"); + exit(1); +} + +static void addport(int fd) +{ + int nfd = nfdpoll; + t_fdpoll *fp; + fdpoll = (t_fdpoll *)realloc(fdpoll, + (nfdpoll+1) * sizeof(t_fdpoll)); + fp = fdpoll + nfdpoll; + fp->fdp_fd = fd; + nfdpoll++; + if (fd >= maxfd) maxfd = fd + 1; + fp->fdp_outlen = fp->fdp_discard = fp->fdp_gotsemi = 0; + if (!(fp->fdp_outbuf = (char*) malloc(BUFSIZE))) + { + fprintf(stderr, "out of memory"); + exit(1); + } + printf("number_connected %d;\n", nfdpoll); +} + +static void rmport(t_fdpoll *x) +{ + int nfd = nfdpoll; + int i, size = nfdpoll * sizeof(t_fdpoll); + t_fdpoll *fp; + for (i = nfdpoll, fp = fdpoll; i--; fp++) + { + if (fp == x) + { + x_closesocket(fp->fdp_fd); + free(fp->fdp_outbuf); + while (i--) + { + fp[0] = fp[1]; + fp++; + } + fdpoll = (t_fdpoll *)realloc(fdpoll, + (nfdpoll-1) * sizeof(t_fdpoll)); + nfdpoll--; + printf("number_connected %d;\n", nfdpoll); + return; + } + } + fprintf(stderr, "warning: item removed from poll list but not found"); +} + +static void doconnect(void) +{ + int fd = accept(sockfd, 0, 0); + if (fd < 0) + perror("accept"); + else addport(fd); +} + +static void makeoutput(char *buf, int len) +{ +#ifdef _WIN32 + int j; + for (j = 0; j < len; j++) + putchar(buf[j]); +#else + if (write(1, buf, len) < len) + { + perror("write"); + exit(1); + } +#endif +} + +static void udpread(void) +{ + char buf[BUFSIZE]; + int ret = recv(sockfd, buf, BUFSIZE, 0); + if (ret < 0) + { + sockerror("recv (udp)"); + x_closesocket(sockfd); + exit(1); + } + else if (ret > 0) + makeoutput(buf, ret); +} + +static int tcpmakeoutput(t_fdpoll *x, char *inbuf, int len) +{ + int i; + int outlen = x->fdp_outlen; + char *outbuf = x->fdp_outbuf; + + for (i = 0 ; i < len ; i++) + { + char c = inbuf[i]; + + if((c != '\n') || (!x->fdp_gotsemi)) + outbuf[outlen++] = c; + x->fdp_gotsemi = 0; + if (outlen >= (BUFSIZE-1)) /*output buffer overflow; reserve 1 for '\n' */ + { + fprintf(stderr, "pdreceive: message too long; discarding\n"); + outlen = 0; + x->fdp_discard = 1; + } + /* search for a semicolon. */ + if (c == ';') + { + outbuf[outlen++] = '\n'; + if (!x->fdp_discard) + makeoutput(outbuf, outlen); + + outlen = 0; + x->fdp_discard = 0; + x->fdp_gotsemi = 1; + } /* if (c == ';') */ + } /* for */ + + x->fdp_outlen = outlen; + return (0); +} + +static void tcpread(t_fdpoll *x) +{ + int ret; + char inbuf[BUFSIZE]; + + ret = recv(x->fdp_fd, inbuf, BUFSIZE, 0); + if (ret < 0) + { + sockerror("recv (tcp)"); + rmport(x); + } + else if (ret == 0) + rmport(x); + else tcpmakeoutput(x, inbuf, ret); +} + +static void dopoll(void) +{ + int i; + t_fdpoll *fp; + fd_set readset, writeset, exceptset; + FD_ZERO(&writeset); + FD_ZERO(&readset); + FD_ZERO(&exceptset); + + FD_SET(sockfd, &readset); + if (protocol == SOCK_STREAM) + { + for (fp = fdpoll, i = nfdpoll; i--; fp++) + FD_SET(fp->fdp_fd, &readset); + } + if (select(maxfd+1, &readset, &writeset, &exceptset, 0) < 0) + { + perror("select"); + exit(1); + } + if (protocol == SOCK_STREAM) + { + for (i = 0; i < nfdpoll; i++) + if (FD_ISSET(fdpoll[i].fdp_fd, &readset)) + tcpread(&fdpoll[i]); + if (FD_ISSET(sockfd, &readset)) + doconnect(); + } + else + { + if (FD_ISSET(sockfd, &readset)) + udpread(); + } +} + + +static void sockerror(char *s) +{ +#ifdef _WIN32 + int err = WSAGetLastError(); + if (err == 10054) return; + else if (err == 10044) + { + fprintf(stderr, + "Warning: you might not have TCP/IP \"networking\" turned on\n"); + } +#else + int err = errno; +#endif + fprintf(stderr, "%s: %s (%d)\n", s, strerror(err), err); +} + +static void x_closesocket(int fd) +{ +#ifdef _WIN32 + closesocket(fd); +#else + close(fd); +#endif +} diff --git a/ports/camomile/source/LibPd/pure-data/src/u_pdsend.c b/ports/camomile/source/LibPd/pure-data/src/u_pdsend.c new file mode 100644 index 00000000..c9b43235 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/u_pdsend.c @@ -0,0 +1,158 @@ +/* Copyright (c) 2000 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in the Pd distribution. */ + +/* the "pdsend" command. This is a standalone program that forwards messages +from its standard input to Pd via the netsend/netreceive ("FUDI") protocol. */ + +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include +#else +#include +#include +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#endif + +void sockerror(char *s); +void x_closesocket(int fd); +#define BUFSIZE 4096 + +int main(int argc, char **argv) +{ + int sockfd, portno, protocol; + struct sockaddr_in server = {0}; + struct hostent *hp; + char *hostname; + int nretry = 10; +#ifdef _WIN32 + short version = MAKEWORD(2, 0); + WSADATA nobby; +#endif + if (argc < 2 || sscanf(argv[1], "%d", &portno) < 1 || portno <= 0) + goto usage; + if (argc >= 3) + hostname = argv[2]; + else hostname = "127.0.0.1"; + if (argc >= 4) + { + if (!strcmp(argv[3], "tcp")) + protocol = SOCK_STREAM; + else if (!strcmp(argv[3], "udp")) + protocol = SOCK_DGRAM; + else goto usage; + } + else protocol = SOCK_STREAM; +#ifdef _WIN32 + if (WSAStartup(version, &nobby)) sockerror("WSAstartup"); +#endif + + sockfd = socket(AF_INET, protocol, 0); + if (sockfd < 0) + { + sockerror("socket()"); + exit(1); + } + /* connect socket using hostname provided in command line */ + server.sin_family = AF_INET; + hp = gethostbyname(hostname); + if (hp == 0) + { + fprintf(stderr, "%s: unknown host\n", hostname); + x_closesocket(sockfd); + exit(1); + } + memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); + + /* assign client port number */ + server.sin_port = htons((unsigned short)portno); + +#if 0 /* try this again for 4.0; this crashed my RH 6.2 machine!) */ + + /* try to connect. */ + for (nretry = 0; nretry < (protocol == SOCK_STREAM ? 10 : 1); nretry++) + + { + if (nretry > 0) + { + sleep (nretry < 5 ? 1 : 5); + fprintf(stderr, "retrying..."); + } + if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) >= 0) + goto connected; + sockerror("connect"); + } + x_closesocket(sockfd); + exit(1); +connected: ; +#else + /* try to connect. */ + if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) + { + sockerror("connect"); + x_closesocket(sockfd); + exit(1); + } +#endif + /* now loop reading stdin and sending it to socket */ + while (1) + { + char buf[BUFSIZE], *bp; + int nsent, nsend; + if (!fgets(buf, BUFSIZE, stdin)) + break; + nsend = strlen(buf); + for (bp = buf, nsent = 0; nsent < nsend;) + { + int res = send(sockfd, bp, nsend-nsent, 0); + if (res < 0) + { + sockerror("send"); + goto done; + } + nsent += res; + bp += res; + } + } +done: + if (ferror(stdin)) + perror("stdin"); + exit (0); +usage: + fprintf(stderr, "usage: pdsend [host] [udp|tcp]\n"); + fprintf(stderr, "(default is localhost and tcp)\n"); + exit(1); +} + +void sockerror(char *s) +{ +#ifdef _WIN32 + int err = WSAGetLastError(); + if (err == 10054) return; + else if (err == 10044) + { + fprintf(stderr, + "Warning: you might not have TCP/IP \"networking\" turned on\n"); + } +#else + int err = errno; +#endif + fprintf(stderr, "%s: %s (%d)\n", s, strerror(err), err); +} + +void x_closesocket(int fd) +{ +#ifdef _WIN32 + closesocket(fd); +#else + close(fd); +#endif +} diff --git a/ports/camomile/source/LibPd/pure-data/src/x_acoustics.c b/ports/camomile/source/LibPd/pure-data/src/x_acoustics.c new file mode 100644 index 00000000..101dfad3 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_acoustics.c @@ -0,0 +1,193 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* utility functions for signals +*/ + +#include "m_pd.h" +#include +#define LOGTEN 2.302585092994 + +t_float mtof(t_float f) +{ + if (f <= -1500) return(0); + else if (f > 1499) return(mtof(1499)); + else return (8.17579891564 * exp(.0577622650 * f)); +} + +t_float ftom(t_float f) +{ + return (f > 0 ? 17.3123405046 * log(.12231220585 * f) : -1500); +} + +t_float powtodb(t_float f) +{ + if (f <= 0) return (0); + else + { + t_float val = 100 + 10./LOGTEN * log(f); + return (val < 0 ? 0 : val); + } +} + +t_float rmstodb(t_float f) +{ + if (f <= 0) return (0); + else + { + t_float val = 100 + 20./LOGTEN * log(f); + return (val < 0 ? 0 : val); + } +} + +t_float dbtopow(t_float f) +{ + if (f <= 0) + return(0); + else + { + if (f > 870) + f = 870; + return (exp((LOGTEN * 0.1) * (f-100.))); + } +} + +t_float dbtorms(t_float f) +{ + if (f <= 0) + return(0); + else + { + if (f > 485) + f = 485; + } + return (exp((LOGTEN * 0.05) * (f-100.))); +} + +/* ------------- corresponding objects ----------------------- */ + +static t_class *mtof_class; + +static void *mtof_new(void) +{ + t_object *x = (t_object *)pd_new(mtof_class); + outlet_new(x, &s_float); + return (x); +} + +static void mtof_float(t_object *x, t_float f) +{ + outlet_float(x->ob_outlet, mtof(f)); +} + + +static t_class *ftom_class; + +static void *ftom_new(void) +{ + t_object *x = (t_object *)pd_new(ftom_class); + outlet_new(x, &s_float); + return (x); +} + +static void ftom_float(t_object *x, t_float f) +{ + outlet_float(x->ob_outlet, ftom(f)); +} + + +static t_class *rmstodb_class; + +static void *rmstodb_new(void) +{ + t_object *x = (t_object *)pd_new(rmstodb_class); + outlet_new(x, &s_float); + return (x); +} + +static void rmstodb_float(t_object *x, t_float f) +{ + outlet_float(x->ob_outlet, rmstodb(f)); +} + + +static t_class *powtodb_class; + +static void *powtodb_new(void) +{ + t_object *x = (t_object *)pd_new(powtodb_class); + outlet_new(x, &s_float); + return (x); +} + +static void powtodb_float(t_object *x, t_float f) +{ + outlet_float(x->ob_outlet, powtodb(f)); +} + + +static t_class *dbtopow_class; + +static void *dbtopow_new(void) +{ + t_object *x = (t_object *)pd_new(dbtopow_class); + outlet_new(x, &s_float); + return (x); +} + +static void dbtopow_float(t_object *x, t_float f) +{ + outlet_float(x->ob_outlet, dbtopow(f)); +} + + +static t_class *dbtorms_class; + +static void *dbtorms_new(void) +{ + t_object *x = (t_object *)pd_new(dbtorms_class); + outlet_new(x, &s_float); + return (x); +} + +static void dbtorms_float(t_object *x, t_float f) +{ + outlet_float(x->ob_outlet, dbtorms(f)); +} + + +void x_acoustics_setup(void) +{ + t_symbol *s = gensym("acoustics.pd"); + mtof_class = class_new(gensym("mtof"), mtof_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(mtof_class, (t_method)mtof_float); + class_sethelpsymbol(mtof_class, s); + + ftom_class = class_new(gensym("ftom"), ftom_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(ftom_class, (t_method)ftom_float); + class_sethelpsymbol(ftom_class, s); + + powtodb_class = class_new(gensym("powtodb"), powtodb_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(powtodb_class, (t_method)powtodb_float); + class_sethelpsymbol(powtodb_class, s); + + rmstodb_class = class_new(gensym("rmstodb"), rmstodb_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(rmstodb_class, (t_method)rmstodb_float); + class_sethelpsymbol(rmstodb_class, s); + + dbtopow_class = class_new(gensym("dbtopow"), dbtopow_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(dbtopow_class, (t_method)dbtopow_float); + class_sethelpsymbol(dbtopow_class, s); + + dbtorms_class = class_new(gensym("dbtorms"), dbtorms_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(dbtorms_class, (t_method)dbtorms_float); + class_sethelpsymbol(dbtorms_class, s); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/x_arithmetic.c b/ports/camomile/source/LibPd/pure-data/src/x_arithmetic.c new file mode 100644 index 00000000..696eb4fe --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_arithmetic.c @@ -0,0 +1,916 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* arithmetic: binops ala C language. The 4 functions and relationals are +done on floats; the logical and bitwise binops convert their +inputs to int and their outputs back to float. */ + +#include "m_pd.h" +#include + + +typedef struct _binop +{ + t_object x_obj; + t_float x_f1; + t_float x_f2; +} t_binop; + +/* ------------------ binop1: +, -, *, / ----------------------------- */ + +static void *binop1_new(t_class *floatclass, t_floatarg f) +{ + t_binop *x = (t_binop *)pd_new(floatclass); + outlet_new(&x->x_obj, &s_float); + floatinlet_new(&x->x_obj, &x->x_f2); + x->x_f1 = 0; + x->x_f2 = f; + return (x); +} + +/* --------------------- addition ------------------------------- */ + +static t_class *binop1_plus_class; + +static void *binop1_plus_new(t_floatarg f) +{ + return (binop1_new(binop1_plus_class, f)); +} + +static void binop1_plus_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, x->x_f1 + x->x_f2); +} + +static void binop1_plus_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, (x->x_f1 = f) + x->x_f2); +} + +/* --------------------- subtraction ------------------------------- */ + +static t_class *binop1_minus_class; + +static void *binop1_minus_new(t_floatarg f) +{ + return (binop1_new(binop1_minus_class, f)); +} + +static void binop1_minus_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, x->x_f1 - x->x_f2); +} + +static void binop1_minus_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, (x->x_f1 = f) - x->x_f2); +} + +/* --------------------- multiplication ------------------------------- */ + +static t_class *binop1_times_class; + +static void *binop1_times_new(t_floatarg f) +{ + return (binop1_new(binop1_times_class, f)); +} + +static void binop1_times_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, x->x_f1 * x->x_f2); +} + +static void binop1_times_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, (x->x_f1 = f) * x->x_f2); +} + +/* --------------------- division ------------------------------- */ + +static t_class *binop1_div_class; + +static void *binop1_div_new(t_floatarg f) +{ + return (binop1_new(binop1_div_class, f)); +} + +static void binop1_div_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, + (x->x_f2 != 0 ? x->x_f1 / x->x_f2 : 0)); +} + +static void binop1_div_float(t_binop *x, t_float f) +{ + x->x_f1 = f; + outlet_float(x->x_obj.ob_outlet, + (x->x_f2 != 0 ? x->x_f1 / x->x_f2 : 0)); +} + +/* ------------------------ pow -------------------------------- */ + +static t_class *binop1_pow_class; + +static void *binop1_pow_new(t_floatarg f) +{ + return (binop1_new(binop1_pow_class, f)); +} + +static void binop1_pow_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, + (x->x_f1 > 0 ? powf(x->x_f1, x->x_f2) : 0)); +} + +static void binop1_pow_float(t_binop *x, t_float f) +{ + x->x_f1 = f; + outlet_float(x->x_obj.ob_outlet, + (x->x_f1 > 0 ? powf(x->x_f1, x->x_f2) : 0)); +} + +/* ------------------------ max -------------------------------- */ + +static t_class *binop1_max_class; + +static void *binop1_max_new(t_floatarg f) +{ + return (binop1_new(binop1_max_class, f)); +} + +static void binop1_max_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, + (x->x_f1 > x->x_f2 ? x->x_f1 : x->x_f2)); +} + +static void binop1_max_float(t_binop *x, t_float f) +{ + x->x_f1 = f; + outlet_float(x->x_obj.ob_outlet, + (x->x_f1 > x->x_f2 ? x->x_f1 : x->x_f2)); +} + +/* ------------------------ min -------------------------------- */ + +static t_class *binop1_min_class; + +static void *binop1_min_new(t_floatarg f) +{ + return (binop1_new(binop1_min_class, f)); +} + +static void binop1_min_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, + (x->x_f1 < x->x_f2 ? x->x_f1 : x->x_f2)); +} + +static void binop1_min_float(t_binop *x, t_float f) +{ + x->x_f1 = f; + outlet_float(x->x_obj.ob_outlet, + (x->x_f1 < x->x_f2 ? x->x_f1 : x->x_f2)); +} + +/* ------------------ binop2: ==, !=, >, <, >=, <=. -------------------- */ + +static void *binop2_new(t_class *floatclass, t_floatarg f) +{ + t_binop *x = (t_binop *)pd_new(floatclass); + outlet_new(&x->x_obj, &s_float); + floatinlet_new(&x->x_obj, &x->x_f2); + x->x_f1 = 0; + x->x_f2 = f; + return (x); +} + +/* --------------------- == ------------------------------- */ + +static t_class *binop2_ee_class; + +static void *binop2_ee_new(t_floatarg f) +{ + return (binop2_new(binop2_ee_class, f)); +} + +static void binop2_ee_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, x->x_f1 == x->x_f2); +} + +static void binop2_ee_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, (x->x_f1 = f) == x->x_f2); +} + +/* --------------------- != ------------------------------- */ + +static t_class *binop2_ne_class; + +static void *binop2_ne_new(t_floatarg f) +{ + return (binop2_new(binop2_ne_class, f)); +} + +static void binop2_ne_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, x->x_f1 != x->x_f2); +} + +static void binop2_ne_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, (x->x_f1 = f) != x->x_f2); +} + +/* --------------------- > ------------------------------- */ + +static t_class *binop2_gt_class; + +static void *binop2_gt_new(t_floatarg f) +{ + return (binop2_new(binop2_gt_class, f)); +} + +static void binop2_gt_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, x->x_f1 > x->x_f2); +} + +static void binop2_gt_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, (x->x_f1 = f) > x->x_f2); +} + +/* --------------------- < ------------------------------- */ + +static t_class *binop2_lt_class; + +static void *binop2_lt_new(t_floatarg f) +{ + return (binop2_new(binop2_lt_class, f)); +} + +static void binop2_lt_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, x->x_f1 < x->x_f2); +} + +static void binop2_lt_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, (x->x_f1 = f) < x->x_f2); +} + +/* --------------------- >= ------------------------------- */ + +static t_class *binop2_ge_class; + +static void *binop2_ge_new(t_floatarg f) +{ + return (binop2_new(binop2_ge_class, f)); +} + +static void binop2_ge_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, x->x_f1 >= x->x_f2); +} + +static void binop2_ge_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, (x->x_f1 = f) >= x->x_f2); +} + +/* --------------------- <= ------------------------------- */ + +static t_class *binop2_le_class; + +static void *binop2_le_new(t_floatarg f) +{ + return (binop2_new(binop2_le_class, f)); +} + +static void binop2_le_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, x->x_f1 <= x->x_f2); +} + +static void binop2_le_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, (x->x_f1 = f) <= x->x_f2); +} + +/* ------------- binop3: &, |, &&, ||, <<, >>, %, mod, div ------------------ */ + +static void *binop3_new(t_class *fixclass, t_floatarg f) +{ + t_binop *x = (t_binop *)pd_new(fixclass); + outlet_new(&x->x_obj, &s_float); + floatinlet_new(&x->x_obj, &x->x_f2); + x->x_f1 = 0; + x->x_f2 = f; + return (x); +} + +/* --------------------------- & ---------------------------- */ + +static t_class *binop3_ba_class; + +static void *binop3_ba_new(t_floatarg f) +{ + return (binop3_new(binop3_ba_class, f)); +} + +static void binop2_ba_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, ((int)(x->x_f1)) & (int)(x->x_f2)); +} + +static void binop2_ba_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, ((int)(x->x_f1 = f)) & (int)(x->x_f2)); +} + +/* --------------------------- && ---------------------------- */ + +static t_class *binop3_la_class; + +static void *binop3_la_new(t_floatarg f) +{ + return (binop3_new(binop3_la_class, f)); +} + +static void binop2_la_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, ((int)(x->x_f1)) && (int)(x->x_f2)); +} + +static void binop2_la_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, ((int)(x->x_f1 = f)) && (int)(x->x_f2)); +} + +/* --------------------------- | ---------------------------- */ + +static t_class *binop3_bo_class; + +static void *binop3_bo_new(t_floatarg f) +{ + return (binop3_new(binop3_bo_class, f)); +} + +static void binop2_bo_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, ((int)(x->x_f1)) | (int)(x->x_f2)); +} + +static void binop2_bo_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, ((int)(x->x_f1 = f)) | (int)(x->x_f2)); +} + +/* --------------------------- || ---------------------------- */ + +static t_class *binop3_lo_class; + +static void *binop3_lo_new(t_floatarg f) +{ + return (binop3_new(binop3_lo_class, f)); +} + +static void binop2_lo_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, ((int)(x->x_f1)) || (int)(x->x_f2)); +} + +static void binop2_lo_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, ((int)(x->x_f1 = f)) || (int)(x->x_f2)); +} + +/* --------------------------- << ---------------------------- */ + +static t_class *binop3_ls_class; + +static void *binop3_ls_new(t_floatarg f) +{ + return (binop3_new(binop3_ls_class, f)); +} + +static void binop2_ls_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, ((int)(x->x_f1)) << (int)(x->x_f2)); +} + +static void binop2_ls_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, ((int)(x->x_f1 = f)) << (int)(x->x_f2)); +} + +/* --------------------------- >> ---------------------------- */ + +static t_class *binop3_rs_class; + +static void *binop3_rs_new(t_floatarg f) +{ + return (binop3_new(binop3_rs_class, f)); +} + +static void binop2_rs_bang(t_binop *x) +{ + outlet_float(x->x_obj.ob_outlet, ((int)(x->x_f1)) >> (int)(x->x_f2)); +} + +static void binop2_rs_float(t_binop *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, ((int)(x->x_f1 = f)) >> (int)(x->x_f2)); +} + +/* --------------------------- % ---------------------------- */ + +static t_class *binop3_pc_class; + +static void *binop3_pc_new(t_floatarg f) +{ + return (binop3_new(binop3_pc_class, f)); +} + +static void binop2_pc_bang(t_binop *x) +{ + int n2 = x->x_f2; + /* apparently "%" raises an exception for INT_MIN and -1 */ + if (n2 == -1) + outlet_float(x->x_obj.ob_outlet, 0); + else outlet_float(x->x_obj.ob_outlet, ((int)(x->x_f1)) % (n2 ? n2 : 1)); +} + +static void binop2_pc_float(t_binop *x, t_float f) +{ + int n2 = x->x_f2; + if (n2 == -1) + outlet_float(x->x_obj.ob_outlet, 0); + else outlet_float(x->x_obj.ob_outlet, ((int)(x->x_f1 = f)) % (n2 ? n2 : 1)); +} + +/* --------------------------- mod ---------------------------- */ + +static t_class *binop3_mod_class; + +static void *binop3_mod_new(t_floatarg f) +{ + return (binop3_new(binop3_mod_class, f)); +} + +static void binop3_mod_bang(t_binop *x) +{ + int n2 = x->x_f2, result; + if (n2 < 0) n2 = -n2; + else if (!n2) n2 = 1; + result = ((int)(x->x_f1)) % n2; + if (result < 0) result += n2; + outlet_float(x->x_obj.ob_outlet, (t_float)result); +} + +static void binop3_mod_float(t_binop *x, t_float f) +{ + x->x_f1 = f; + binop3_mod_bang(x); +} + +/* --------------------------- div ---------------------------- */ + +static t_class *binop3_div_class; + +static void *binop3_div_new(t_floatarg f) +{ + return (binop3_new(binop3_div_class, f)); +} + +static void binop3_div_bang(t_binop *x) +{ + int n1 = x->x_f1, n2 = x->x_f2, result; + if (n2 < 0) n2 = -n2; + else if (!n2) n2 = 1; + if (n1 < 0) n1 -= (n2-1); + result = n1 / n2; + outlet_float(x->x_obj.ob_outlet, (t_float)result); +} + +static void binop3_div_float(t_binop *x, t_float f) +{ + x->x_f1 = f; + binop3_div_bang(x); +} + +/* -------------------- mathematical functions ------------------ */ + +static t_class *sin_class; /* ----------- sin --------------- */ + +static void *sin_new(void) +{ + t_object *x = (t_object *)pd_new(sin_class); + outlet_new(x, &s_float); + return (x); +} + +static void sin_float(t_object *x, t_float f) +{ + outlet_float(x->ob_outlet, sinf(f)); +} + +static t_class *cos_class; /* ----------- cos --------------- */ + +static void *cos_new(void) +{ + t_object *x = (t_object *)pd_new(cos_class); + outlet_new(x, &s_float); + return (x); +} + +static void cos_float(t_object *x, t_float f) +{ + outlet_float(x->ob_outlet, cosf(f)); +} + +static t_class *tan_class; /* ----------- tan --------------- */ + +static void *tan_new(void) +{ + t_object *x = (t_object *)pd_new(tan_class); + outlet_new(x, &s_float); + return (x); +} + +static void tan_float(t_object *x, t_float f) +{ + t_float c = cosf(f); + t_float t = (c == 0 ? 0 : sinf(f)/c); + outlet_float(x->ob_outlet, t); +} + +static t_class *atan_class; /* ----------- atan --------------- */ + +static void *atan_new(void) +{ + t_object *x = (t_object *)pd_new(atan_class); + outlet_new(x, &s_float); + return (x); +} + +static void atan_float(t_object *x, t_float f) +{ + outlet_float(x->ob_outlet, atanf(f)); +} + +static t_class *atan2_class; /* ----------- atan2 --------------- */ + +typedef struct _atan2 +{ + t_object x_ob; + t_float x_f; +} t_atan2; + +static void *atan2_new(void) +{ + t_atan2 *x = (t_atan2 *)pd_new(atan2_class); + floatinlet_new(&x->x_ob, &x->x_f); + x->x_f = 0; + outlet_new(&x->x_ob, &s_float); + return (x); +} + +static void atan2_float(t_atan2 *x, t_float f) +{ + t_float r = (f == 0 && x->x_f == 0 ? 0 : atan2f(f, x->x_f)); + outlet_float(x->x_ob.ob_outlet, r); +} + +static t_class *sqrt_class; /* ----------- sqrt --------------- */ + +static void *sqrt_new(void) +{ + t_object *x = (t_object *)pd_new(sqrt_class); + outlet_new(x, &s_float); + return (x); +} + +static void sqrt_float(t_object *x, t_float f) +{ + t_float r = (f > 0 ? sqrtf(f) : 0); + outlet_float(x->ob_outlet, r); +} + +static t_class *log_class; /* ----------- log --------------- */ + +static void *log_new(void) +{ + t_object *x = (t_object *)pd_new(log_class); + outlet_new(x, &s_float); + return (x); +} + +static void log_float(t_object *x, t_float f) +{ + t_float r = (f > 0 ? logf(f) : -1000); + outlet_float(x->ob_outlet, r); +} + +static t_class *exp_class; /* ----------- exp --------------- */ + +static void *exp_new(void) +{ + t_object *x = (t_object *)pd_new(exp_class); + outlet_new(x, &s_float); + return (x); +} + +#define MAXLOG 87.3365 +static void exp_float(t_object *x, t_float f) +{ + t_float g; +#ifdef _WIN32 + char buf[10]; +#endif + if (f > MAXLOG) f = MAXLOG; + g = expf(f); + outlet_float(x->ob_outlet, g); +} + +static t_class *abs_class; /* ----------- abs --------------- */ + +static void *abs_new(void) +{ + t_object *x = (t_object *)pd_new(abs_class); + outlet_new(x, &s_float); + return (x); +} + +static void abs_float(t_object *x, t_float f) +{ + outlet_float(x->ob_outlet, fabsf(f)); +} + +static t_class *wrap_class; /* ----------- wrap --------------- */ + +static void *wrap_new(void) +{ + t_object *x = (t_object *)pd_new(wrap_class); + outlet_new(x, &s_float); + return (x); +} + +static void wrap_float(t_object *x, t_float f) +{ + outlet_float(x->ob_outlet, f - floor(f)); +} + +/* ------------------------ misc ------------------------ */ + +static t_class *clip_class; + +typedef struct _clip +{ + t_object x_ob; + t_float x_f1; + t_float x_f2; + t_float x_f3; +} t_clip; + +static void *clip_new(t_floatarg f1, t_floatarg f2) +{ + t_clip *x = (t_clip *)pd_new(clip_class); + floatinlet_new(&x->x_ob, &x->x_f2); + floatinlet_new(&x->x_ob, &x->x_f3); + outlet_new(&x->x_ob, &s_float); + x->x_f2 = f1; + x->x_f3 = f2; + return (x); +} + +static void clip_bang(t_clip *x) +{ + outlet_float(x->x_ob.ob_outlet, (x->x_f1 < x->x_f2 ? x->x_f2 : ( + x->x_f1 > x->x_f3 ? x->x_f3 : x->x_f1))); +} + +static void clip_float(t_clip *x, t_float f) +{ + x->x_f1 = f; + outlet_float(x->x_ob.ob_outlet, (x->x_f1 < x->x_f2 ? x->x_f2 : ( + x->x_f1 > x->x_f3 ? x->x_f3 : x->x_f1))); +} + +static void clip_setup(void) +{ + clip_class = class_new(gensym("clip"), (t_newmethod)clip_new, 0, + sizeof(t_clip), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addfloat(clip_class, clip_float); + class_addbang(clip_class, clip_bang); +} + +void x_arithmetic_setup(void) +{ + t_symbol *binop1_sym = gensym("operators"); + t_symbol *binop23_sym = gensym("otherbinops"); + t_symbol *math_sym = gensym("math"); + + binop1_plus_class = class_new(gensym("+"), (t_newmethod)binop1_plus_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop1_plus_class, binop1_plus_bang); + class_addfloat(binop1_plus_class, (t_method)binop1_plus_float); + class_sethelpsymbol(binop1_plus_class, binop1_sym); + + binop1_minus_class = class_new(gensym("-"), + (t_newmethod)binop1_minus_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop1_minus_class, binop1_minus_bang); + class_addfloat(binop1_minus_class, (t_method)binop1_minus_float); + class_sethelpsymbol(binop1_minus_class, binop1_sym); + + binop1_times_class = class_new(gensym("*"), + (t_newmethod)binop1_times_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop1_times_class, binop1_times_bang); + class_addfloat(binop1_times_class, (t_method)binop1_times_float); + class_sethelpsymbol(binop1_times_class, binop1_sym); + + binop1_div_class = class_new(gensym("/"), + (t_newmethod)binop1_div_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop1_div_class, binop1_div_bang); + class_addfloat(binop1_div_class, (t_method)binop1_div_float); + class_sethelpsymbol(binop1_div_class, binop1_sym); + + binop1_pow_class = class_new(gensym("pow"), + (t_newmethod)binop1_pow_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop1_pow_class, binop1_pow_bang); + class_addfloat(binop1_pow_class, (t_method)binop1_pow_float); + class_sethelpsymbol(binop1_pow_class, binop1_sym); + + binop1_max_class = class_new(gensym("max"), + (t_newmethod)binop1_max_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop1_max_class, binop1_max_bang); + class_addfloat(binop1_max_class, (t_method)binop1_max_float); + class_sethelpsymbol(binop1_max_class, binop1_sym); + + binop1_min_class = class_new(gensym("min"), + (t_newmethod)binop1_min_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop1_min_class, binop1_min_bang); + class_addfloat(binop1_min_class, (t_method)binop1_min_float); + class_sethelpsymbol(binop1_min_class, binop1_sym); + + /* ------------------ binop2 ----------------------- */ + + binop2_ee_class = class_new(gensym("=="), (t_newmethod)binop2_ee_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop2_ee_class, binop2_ee_bang); + class_addfloat(binop2_ee_class, (t_method)binop2_ee_float); + class_sethelpsymbol(binop2_ee_class, binop23_sym); + + binop2_ne_class = class_new(gensym("!="), (t_newmethod)binop2_ne_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop2_ne_class, binop2_ne_bang); + class_addfloat(binop2_ne_class, (t_method)binop2_ne_float); + class_sethelpsymbol(binop2_ne_class, binop23_sym); + + binop2_gt_class = class_new(gensym(">"), (t_newmethod)binop2_gt_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop2_gt_class, binop2_gt_bang); + class_addfloat(binop2_gt_class, (t_method)binop2_gt_float); + class_sethelpsymbol(binop2_gt_class, binop23_sym); + + binop2_lt_class = class_new(gensym("<"), (t_newmethod)binop2_lt_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop2_lt_class, binop2_lt_bang); + class_addfloat(binop2_lt_class, (t_method)binop2_lt_float); + class_sethelpsymbol(binop2_lt_class, binop23_sym); + + binop2_ge_class = class_new(gensym(">="), (t_newmethod)binop2_ge_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop2_ge_class, binop2_ge_bang); + class_addfloat(binop2_ge_class, (t_method)binop2_ge_float); + class_sethelpsymbol(binop2_ge_class, binop23_sym); + + binop2_le_class = class_new(gensym("<="), (t_newmethod)binop2_le_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop2_le_class, binop2_le_bang); + class_addfloat(binop2_le_class, (t_method)binop2_le_float); + class_sethelpsymbol(binop2_le_class, binop23_sym); + + /* ------------------ binop3 ----------------------- */ + + binop3_ba_class = class_new(gensym("&"), (t_newmethod)binop3_ba_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop3_ba_class, binop2_ba_bang); + class_addfloat(binop3_ba_class, (t_method)binop2_ba_float); + class_sethelpsymbol(binop3_ba_class, binop23_sym); + + binop3_la_class = class_new(gensym("&&"), (t_newmethod)binop3_la_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop3_la_class, binop2_la_bang); + class_addfloat(binop3_la_class, (t_method)binop2_la_float); + class_sethelpsymbol(binop3_la_class, binop23_sym); + + binop3_bo_class = class_new(gensym("|"), (t_newmethod)binop3_bo_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop3_bo_class, binop2_bo_bang); + class_addfloat(binop3_bo_class, (t_method)binop2_bo_float); + class_sethelpsymbol(binop3_bo_class, binop23_sym); + + binop3_lo_class = class_new(gensym("||"), (t_newmethod)binop3_lo_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop3_lo_class, binop2_lo_bang); + class_addfloat(binop3_lo_class, (t_method)binop2_lo_float); + class_sethelpsymbol(binop3_lo_class, binop23_sym); + + binop3_ls_class = class_new(gensym("<<"), (t_newmethod)binop3_ls_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop3_ls_class, binop2_ls_bang); + class_addfloat(binop3_ls_class, (t_method)binop2_ls_float); + class_sethelpsymbol(binop3_ls_class, binop23_sym); + + binop3_rs_class = class_new(gensym(">>"), (t_newmethod)binop3_rs_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop3_rs_class, binop2_rs_bang); + class_addfloat(binop3_rs_class, (t_method)binop2_rs_float); + class_sethelpsymbol(binop3_rs_class, binop23_sym); + + binop3_pc_class = class_new(gensym("%"), (t_newmethod)binop3_pc_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop3_pc_class, binop2_pc_bang); + class_addfloat(binop3_pc_class, (t_method)binop2_pc_float); + class_sethelpsymbol(binop3_pc_class, binop23_sym); + + binop3_mod_class = class_new(gensym("mod"), (t_newmethod)binop3_mod_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop3_mod_class, binop3_mod_bang); + class_addfloat(binop3_mod_class, (t_method)binop3_mod_float); + class_sethelpsymbol(binop3_mod_class, binop23_sym); + + binop3_div_class = class_new(gensym("div"), (t_newmethod)binop3_div_new, 0, + sizeof(t_binop), 0, A_DEFFLOAT, 0); + class_addbang(binop3_div_class, binop3_div_bang); + class_addfloat(binop3_div_class, (t_method)binop3_div_float); + class_sethelpsymbol(binop3_div_class, binop23_sym); + + /* ------------------- math functions --------------- */ + + sin_class = class_new(gensym("sin"), sin_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(sin_class, (t_method)sin_float); + class_sethelpsymbol(sin_class, math_sym); + + cos_class = class_new(gensym("cos"), cos_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(cos_class, (t_method)cos_float); + class_sethelpsymbol(cos_class, math_sym); + + tan_class = class_new(gensym("tan"), tan_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(tan_class, (t_method)tan_float); + class_sethelpsymbol(tan_class, math_sym); + + atan_class = class_new(gensym("atan"), atan_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(atan_class, (t_method)atan_float); + class_sethelpsymbol(atan_class, math_sym); + + atan2_class = class_new(gensym("atan2"), atan2_new, 0, + sizeof(t_atan2), 0, 0); + class_addfloat(atan2_class, (t_method)atan2_float); + class_sethelpsymbol(atan2_class, math_sym); + + sqrt_class = class_new(gensym("sqrt"), sqrt_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(sqrt_class, (t_method)sqrt_float); + class_sethelpsymbol(sqrt_class, math_sym); + + log_class = class_new(gensym("log"), log_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(log_class, (t_method)log_float); + class_sethelpsymbol(log_class, math_sym); + + exp_class = class_new(gensym("exp"), exp_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(exp_class, (t_method)exp_float); + class_sethelpsymbol(exp_class, math_sym); + + abs_class = class_new(gensym("abs"), abs_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(abs_class, (t_method)abs_float); + class_sethelpsymbol(abs_class, math_sym); + + wrap_class = class_new(gensym("wrap"), wrap_new, 0, + sizeof(t_object), 0, 0); + class_addfloat(wrap_class, (t_method)wrap_float); + class_sethelpsymbol(wrap_class, math_sym); + +/* ------------------------ misc ------------------------ */ + + clip_setup(); +} + + diff --git a/ports/camomile/source/LibPd/pure-data/src/x_array.c b/ports/camomile/source/LibPd/pure-data/src/x_array.c new file mode 100644 index 00000000..3bdcc065 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_array.c @@ -0,0 +1,928 @@ +/* Copyright (c) 1997-2013 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* The "array" object. */ + +#include "m_pd.h" +#include "g_canvas.h" +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef _WIN32 +#include +#endif + +#ifdef _WIN32 +# include /* MSVC or mingw on windows */ +#elif defined(__linux__) || defined(__APPLE__) +# include /* linux, mac, mingw, cygwin */ +#else +# include /* BSDs for example */ +#endif + +#ifndef HAVE_ALLOCA /* can work without alloca() but we never need it */ +#define HAVE_ALLOCA 1 +#endif +#define TEXT_NGETBYTE 100 /* bigger that this we use alloc, not alloca */ +#if HAVE_ALLOCA +#define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)((n) < TEXT_NGETBYTE ? \ + alloca((n) * sizeof(t_atom)) : getbytes((n) * sizeof(t_atom)))) +#define ATOMS_FREEA(x, n) ( \ + ((n) < TEXT_NGETBYTE || (freebytes((x), (n) * sizeof(t_atom)), 0))) +#else +#define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)getbytes((n) * sizeof(t_atom))) +#define ATOMS_FREEA(x, n) (freebytes((x), (n) * sizeof(t_atom))) +#endif + +/* -- "table" - classic "array define" object by Guenter Geiger --*/ + +static int tabcount = 0; + +static void *table_donew(t_symbol *s, int size, int flags, + int xpix, int ypix) +{ + t_atom a[9]; + t_glist *gl; + t_canvas *x, *z = canvas_getcurrent(); + if (s == &s_) + { + char tabname[255]; + t_symbol *t = gensym("table"); + sprintf(tabname, "%s%d", t->s_name, tabcount++); + s = gensym(tabname); + } + if (size < 1) + size = 100; + SETFLOAT(a, 0); + SETFLOAT(a+1, 50); + SETFLOAT(a+2, xpix + 100); + SETFLOAT(a+3, ypix + 100); + SETSYMBOL(a+4, s); + SETFLOAT(a+5, 0); + x = canvas_new(0, 0, 6, a); + + x->gl_owner = z; + + /* create a graph for the table */ + gl = glist_addglist((t_glist*)x, &s_, 0, -1, (size > 1 ? size-1 : 1), 1, + 50, ypix+50, xpix+50, 50); + + graph_array(gl, s, &s_float, size, flags); + + pd_this->pd_newest = &x->gl_pd; /* mimic action of canvas_pop() */ + pd_popsym(&x->gl_pd); + x->gl_loading = 0; + + return (x); +} + +static void *table_new(t_symbol *s, t_floatarg f) +{ + return (table_donew(s, f, 0, 500, 300)); +} + + /* return true if the "canvas" object is a "table". */ +int canvas_istable(t_canvas *x) +{ + t_atom *argv = (x->gl_obj.te_binbuf? binbuf_getvec(x->gl_obj.te_binbuf):0); + int argc = (x->gl_obj.te_binbuf? binbuf_getnatom(x->gl_obj.te_binbuf) : 0); + int istable = (argc && argv[0].a_type == A_SYMBOL && + argv[0].a_w.w_symbol == gensym("table")); + return (istable); +} + +t_class *array_define_class; + +static void array_define_yrange(t_glist *x, t_floatarg ylo, t_floatarg yhi) +{ + t_glist *gl = (x->gl_list ? pd_checkglist(&x->gl_list->g_pd) : 0); + if (gl && gl->gl_list && pd_class(&gl->gl_list->g_pd) == garray_class) + { + int n = garray_getarray((t_garray *)gl->gl_list)->a_n; + vmess(&x->gl_list->g_pd, gensym("bounds"), + "ffff", 0., yhi, (double)(n == 1 ? n : n-1), ylo); + vmess(&x->gl_list->g_pd, gensym("xlabel"), + "fff", ylo + glist_pixelstoy(gl, 2) - glist_pixelstoy(gl, 0), + 0., (float)(n-1)); + vmess(&x->gl_list->g_pd, gensym("ylabel"), + "fff", glist_pixelstox(gl, 0) - glist_pixelstox(gl, 5), ylo, yhi); + } + else bug("array_define_yrange"); +} + +static void *array_define_new(t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *arrayname = &s_; + float arraysize = 100; + t_glist *x; + int keep = 0; + float ylo = -1, yhi = 1; + float xpix = 500, ypix = 300; + while (argc && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + if (!strcmp(argv->a_w.w_symbol->s_name, "-k")) + keep = 1; + else if (!strcmp(argv->a_w.w_symbol->s_name, "-yrange") && + argc >= 3 && argv[1].a_type == A_FLOAT && + argv[2].a_type == A_FLOAT) + { + ylo = atom_getfloatarg(1, argc, argv); + yhi = atom_getfloatarg(2, argc, argv); + if (ylo == yhi) + ylo = -1, yhi = 1; + argc -= 2; argv += 2; + } + else if (!strcmp(argv->a_w.w_symbol->s_name, "-pix") && + argc >= 3 && argv[1].a_type == A_FLOAT && + argv[2].a_type == A_FLOAT) + { + if ((xpix = atom_getfloatarg(1, argc, argv)) < 10) + xpix = 10; + if ((ypix = atom_getfloatarg(2, argc, argv)) < 10) + ypix = 10; + argc -= 2; argv += 2; + } + else + { + error("array define: unknown flag ..."); + postatom(argc, argv); endpost(); + } + argc--; argv++; + } + if (argc && argv->a_type == A_SYMBOL) + { + arrayname = argv->a_w.w_symbol; + argc--; argv++; + } + if (argc && argv->a_type == A_FLOAT) + { + arraysize = argv->a_w.w_float; + argc--; argv++; + } + if (argc) + { + post("warning: array define ignoring extra argument: "); + postatom(argc, argv); endpost(); + } + x = (t_glist *)table_donew(arrayname, arraysize, keep, xpix, ypix); + + /* bash the class to "array define". We don't do this earlier in + part so that canvas_getcurrent() will work while the glist and + garray are being created. There may be other, unknown side effects. */ + x->gl_obj.ob_pd = array_define_class; + array_define_yrange(x, ylo, yhi); + return (x); +} + +void garray_savecontentsto(t_garray *x, t_binbuf *b); + +void array_define_save(t_gobj *z, t_binbuf *bb) +{ + t_glist *x = (t_glist *)z; + t_glist *gl = (x->gl_list ? pd_checkglist(&x->gl_list->g_pd) : 0); + binbuf_addv(bb, "ssff", &s__X, gensym("obj"), + (float)x->gl_obj.te_xpix, (float)x->gl_obj.te_ypix); + binbuf_addbinbuf(bb, x->gl_obj.ob_binbuf); + binbuf_addsemi(bb); + + if (gl) + { + garray_savecontentsto((t_garray *)gl->gl_list, bb); + obj_saveformat(&x->gl_obj, bb); + } + else + bug("array_define_save"); +} + +t_scalar *garray_getscalar(t_garray *x); + + /* send a pointer to the scalar that owns this array to + whomever is bound to the given symbol */ +static void array_define_send(t_glist *x, t_symbol *s) +{ + t_glist *gl = (x->gl_list ? pd_checkglist(&x->gl_list->g_pd) : 0); + if (!s->s_thing) + pd_error(x, "array_define_send: %s: no such object", s->s_name); + else if (gl && gl->gl_list && pd_class(&gl->gl_list->g_pd) == garray_class) + { + t_gpointer gp; + gpointer_init(&gp); + gpointer_setglist(&gp, gl, + garray_getscalar((t_garray *)gl->gl_list)); + pd_pointer(s->s_thing, &gp); + gpointer_unset(&gp); + } + else bug("array_define_anything"); +} + + /* just forward any messages to the garray */ +static void array_define_anything(t_glist *x, + t_symbol *s, int argc, t_atom *argv) +{ + t_glist *gl = (x->gl_list ? pd_checkglist(&x->gl_list->g_pd) : 0); + if (gl && gl->gl_list && pd_class(&gl->gl_list->g_pd) == garray_class) + typedmess(&gl->gl_list->g_pd, s, argc, argv); + else bug("array_define_anything"); +} + + /* ignore messages like "editmode" */ +static void array_define_ignore(t_glist *x, + t_symbol *s, int argc, t_atom *argv) +{ +} + +/* --- array_client - common code for objects that refer to arrays -- */ + +typedef struct _array_client +{ + t_object tc_obj; + t_symbol *tc_sym; + t_gpointer tc_gp; + t_symbol *tc_struct; + t_symbol *tc_field; + t_canvas *tc_canvas; +} t_array_client; + +#define x_sym x_tc.tc_sym +#define x_struct x_tc.tc_struct +#define x_field x_tc.tc_field +#define x_gp x_tc.tc_gp + + /* find the array for this object. Prints an error message and returns + 0 on failure. */ +static t_array *array_client_getbuf(t_array_client *x, t_glist **glist) +{ + if (x->tc_sym) /* named array object */ + { + t_garray *y = (t_garray *)pd_findbyclass(x->tc_sym, garray_class); + if (y) + { + *glist = garray_getglist(y); + return (garray_getarray(y)); + } + else + { + pd_error(x, "array: couldn't find named array '%s'", + x->tc_sym->s_name); + *glist = 0; + return (0); + } + } + else if (x->tc_struct) /* by pointer */ + { + t_template *template = template_findbyname(x->tc_struct); + t_gstub *gs = x->tc_gp.gp_stub; + t_word *vec; + int onset, type; + t_symbol *arraytype; + if (!template) + { + pd_error(x, "array: couldn't find struct %s", x->tc_struct->s_name); + return (0); + } + if (!gpointer_check(&x->tc_gp, 0)) + { + pd_error(x, "array: stale or empty pointer"); + return (0); + } + if (gs->gs_which == GP_ARRAY) + vec = x->tc_gp.gp_un.gp_w; + else vec = x->tc_gp.gp_un.gp_scalar->sc_vec; + + if (!template_find_field(template, + x->tc_field, &onset, &type, &arraytype)) + { + pd_error(x, "array: no field named %s", x->tc_field->s_name); + return (0); + } + if (type != DT_ARRAY) + { + pd_error(x, "array: field %s not of type array", + x->tc_field->s_name); + return (0); + } + if (gs->gs_which == GP_GLIST) + *glist = gs->gs_un.gs_glist; + else + { + t_array *owner_array = gs->gs_un.gs_array; + while (owner_array->a_gp.gp_stub->gs_which == GP_ARRAY) + owner_array = owner_array->a_gp.gp_stub->gs_un.gs_array; + *glist = owner_array->a_gp.gp_stub->gs_un.gs_glist; + } + return (*(t_array **)(((char *)vec) + onset)); + } + else return (0); /* shouldn't happen */ +} + +static void array_client_senditup(t_array_client *x) +{ + t_glist *glist = 0; + t_array *a = array_client_getbuf(x, &glist); + if (glist) + array_redraw(a, glist); +} + +static void array_client_free(t_array_client *x) +{ + gpointer_unset(&x->tc_gp); +} + +/* ---------- array size : get or set size of an array ---------------- */ +static t_class *array_size_class; + +typedef struct _array_size +{ + t_array_client x_tc; +} t_array_size; +#define x_outlet x_tc.tc_obj.ob_outlet + +static void *array_size_new(t_symbol *s, int argc, t_atom *argv) +{ + t_array_size *x = (t_array_size *)pd_new(array_size_class); + x->x_sym = x->x_struct = x->x_field = 0; + gpointer_init(&x->x_gp); + while (argc && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + if (!strcmp(argv->a_w.w_symbol->s_name, "-s") && + argc >= 3 && argv[1].a_type == A_SYMBOL && + argv[2].a_type == A_SYMBOL) + { + x->x_struct = canvas_makebindsym(argv[1].a_w.w_symbol); + x->x_field = argv[2].a_w.w_symbol; + argc -= 2; argv += 2; + } + else + { + pd_error(x, "array setline: unknown flag ..."); + postatom(argc, argv); endpost(); + } + argc--; argv++; + } + if (argc && argv->a_type == A_SYMBOL) + { + if (x->x_struct) + { + pd_error(x, "array setline: extra names after -s.."); + postatom(argc, argv); endpost(); + } + else x->x_sym = argv->a_w.w_symbol; + argc--; argv++; + } + if (argc) + { + post("warning: array setline ignoring extra argument: "); + postatom(argc, argv); endpost(); + } + if (x->x_struct) + pointerinlet_new(&x->x_tc.tc_obj, &x->x_gp); + else symbolinlet_new(&x->x_tc.tc_obj, &x->x_tc.tc_sym); + outlet_new(&x->x_tc.tc_obj, &s_float); + return (x); +} + +static void array_size_bang(t_array_size *x) +{ + t_glist *glist; + t_array *a = array_client_getbuf(&x->x_tc, &glist); + if (a) + outlet_float(x->x_outlet, a->a_n); +} + +static void array_size_float(t_array_size *x, t_floatarg f) +{ + t_glist *glist; + t_array *a = array_client_getbuf(&x->x_tc, &glist); + if (a) + { + /* if it's a named array object we have to go back and find the + garray (repeating work done in array_client_getbuf()) because + the garray might want to adjust. Maybe array_client_getbuf + should have a return slot for the garray if any? */ + if (x->x_tc.tc_sym) + { + t_garray *y = (t_garray *)pd_findbyclass(x->x_tc.tc_sym, + garray_class); + if (!y) + { + pd_error(x, "no such array '%s'", x->x_tc.tc_sym->s_name); + return; + } + garray_resize(y, f); + } + else + { + int n = f; + if (n < 1) + n = 1; + array_resize_and_redraw(a, glist, n); + } + } +} + +/* ------ range operations - act on a specifiable range in an array ----- */ +static t_class *array_sum_class; + +typedef struct _array_rangeop /* any operation meaningful on a subrange */ +{ + t_array_client x_tc; + t_float x_onset; + t_float x_n; + t_symbol *x_elemfield; + t_symbol *x_elemtemplate; /* unused - perhaps should at least check it */ +} t_array_rangeop; + + /* generic creator for operations on ranges (array {get,set,sum,random, + quantile,search,...} "onsetin" and "nin" are true if we should make + inlets for onset and n - if no inlet for 'n' we also won't allow + it to be specified as an argument. Everything can take an onset but + sometimes we don't need an inlet because it's the inlet itself. In + any case we allow onset to be specified as an argument (even if it's + the 'hot inlet') -- for the same reason as in the 'delay' object. + Finally we can optionally warn if there are extra arguments; some + specific arguments (e.g., search) allow them but most don't. */ +static void *array_rangeop_new(t_class *class, + t_symbol *s, int *argcp, t_atom **argvp, + int onsetin, int nin, int warnextra) +{ + int argc = *argcp; + t_atom *argv = *argvp; + t_array_rangeop *x = (t_array_rangeop *)pd_new(class); + x->x_sym = x->x_struct = x->x_field = 0; + gpointer_init(&x->x_gp); + x->x_elemtemplate = &s_; + x->x_elemfield = gensym("y"); + x->x_onset = 0; + x->x_n = -1; + if (onsetin) + floatinlet_new(&x->x_tc.tc_obj, &x->x_onset); + if (nin) + floatinlet_new(&x->x_tc.tc_obj, &x->x_n); + while (argc && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + if (!strcmp(argv->a_w.w_symbol->s_name, "-s") && + argc >= 3 && argv[1].a_type == A_SYMBOL && + argv[2].a_type == A_SYMBOL) + { + x->x_struct = canvas_makebindsym(argv[1].a_w.w_symbol); + x->x_field = argv[2].a_w.w_symbol; + argc -= 2; argv += 2; + } + else if (!strcmp(argv->a_w.w_symbol->s_name, "-f") && + argc >= 3 && argv[1].a_type == A_SYMBOL && + argv[2].a_type == A_SYMBOL) + { + x->x_elemtemplate = argv[1].a_w.w_symbol; + x->x_elemfield = argv[2].a_w.w_symbol; + argc -= 2; argv += 2; + } + else + { + pd_error(x, "%s: unknown flag ...", class_getname(class)); + postatom(argc, argv); endpost(); + } + argc--; argv++; + } + if (argc && argv->a_type == A_SYMBOL) + { + if (x->x_struct) + { + pd_error(x, "%s: extra names after -s..", class_getname(class)); + postatom(argc, argv); endpost(); + } + else x->x_sym = argv->a_w.w_symbol; + argc--; argv++; + } + if (argc && argv->a_type == A_FLOAT) + { + x->x_onset = argv->a_w.w_float; + argc--; argv++; + } + if (argc && argv->a_type == A_FLOAT) + { + x->x_n = argv->a_w.w_float; + argc--; argv++; + } + if (argc && warnextra) + { + post("warning: %s ignoring extra argument: ", class_getname(class)); + postatom(argc, argv); endpost(); + } + if (x->x_struct) + pointerinlet_new(&x->x_tc.tc_obj, &x->x_gp); + else symbolinlet_new(&x->x_tc.tc_obj, &x->x_tc.tc_sym); + *argcp = argc; + *argvp = argv; + return (x); +} + +static int array_rangeop_getrange(t_array_rangeop *x, + char **firstitemp, int *nitemp, int *stridep, int *arrayonsetp) +{ + t_glist *glist; + t_array *a = array_client_getbuf(&x->x_tc, &glist); + char *elemp; + int stride, fieldonset, arrayonset, nitem, i, type; + t_symbol *arraytype; + double sum; + t_template *template; + if (!a) + return (0); + template = template_findbyname(a->a_templatesym); + if (!template_find_field(template, x->x_elemfield, &fieldonset, + &type, &arraytype) || type != DT_FLOAT) + { + pd_error(x, "can't find field %s in struct %s", + x->x_elemfield->s_name, a->a_templatesym->s_name); + return (0); + } + stride = a->a_elemsize; + arrayonset = x->x_onset; + if (arrayonset < 0) + arrayonset = 0; + else if (arrayonset > a->a_n) + arrayonset = a->a_n; + if (x->x_n < 0) + nitem = a->a_n - arrayonset; + else + { + nitem = x->x_n; + if (nitem + arrayonset > a->a_n) + nitem = a->a_n - arrayonset; + } + *firstitemp = a->a_vec+(fieldonset+arrayonset*stride); + *nitemp = nitem; + *stridep = stride; + *arrayonsetp = arrayonset; + return (1); +} + +/* -------- specific operations on ranges of arrays -------- */ + +/* ---------------- array sum -- add them up ------------------- */ +static t_class *array_sum_class; + +#define t_array_sum t_array_rangeop + +static void *array_sum_new(t_symbol *s, int argc, t_atom *argv) +{ + t_array_sum *x = array_rangeop_new(array_sum_class, s, &argc, &argv, + 0, 1, 1); + outlet_new(&x->x_tc.tc_obj, &s_float); + return (x); +} + +static void array_sum_bang(t_array_rangeop *x) +{ + char *itemp, *firstitem; + int stride, nitem, arrayonset, i; + double sum; + if (!array_rangeop_getrange(x, &firstitem, &nitem, &stride, &arrayonset)) + return; + for (i = 0, sum = 0, itemp = firstitem; i < nitem; i++, itemp += stride) + sum += *(t_float *)itemp; + outlet_float(x->x_outlet, sum); +} + +static void array_sum_float(t_array_rangeop *x, t_floatarg f) +{ + x->x_onset = f; + array_sum_bang(x); +} + +/* ---------------- array get -- output as list ------------------- */ +static t_class *array_get_class; + +#define t_array_get t_array_rangeop + +static void *array_get_new(t_symbol *s, int argc, t_atom *argv) +{ + t_array_get *x = array_rangeop_new(array_get_class, s, &argc, &argv, + 0, 1, 1); + outlet_new(&x->x_tc.tc_obj, &s_float); + return (x); +} + +static void array_get_bang(t_array_rangeop *x) +{ + char *itemp, *firstitem; + int stride, nitem, arrayonset, i; + t_atom *outv; + if (!array_rangeop_getrange(x, &firstitem, &nitem, &stride, &arrayonset)) + return; + ATOMS_ALLOCA(outv, nitem); + for (i = 0, itemp = firstitem; i < nitem; i++, itemp += stride) + SETFLOAT(&outv[i], *(t_float *)itemp); + outlet_list(x->x_outlet, 0, nitem, outv); + ATOMS_FREEA(outv, nitem); +} + +static void array_get_float(t_array_rangeop *x, t_floatarg f) +{ + x->x_onset = f; + array_get_bang(x); +} + +/* -------------- array set -- copy list to array -------------- */ +static t_class *array_set_class; + +#define t_array_set t_array_rangeop + +static void *array_set_new(t_symbol *s, int argc, t_atom *argv) +{ + t_array_set *x = array_rangeop_new(array_set_class, s, &argc, &argv, + 1, 0, 1); + return (x); +} + +static void array_set_list(t_array_rangeop *x, t_symbol *s, + int argc, t_atom *argv) +{ + char *itemp, *firstitem; + int stride, nitem, arrayonset, i; + if (!array_rangeop_getrange(x, &firstitem, &nitem, &stride, &arrayonset)) + return; + if (nitem > argc) + nitem = argc; + for (i = 0, itemp = firstitem; i < nitem; i++, itemp += stride) + *(t_float *)itemp = atom_getfloatarg(i, argc, argv); + array_client_senditup(&x->x_tc); +} + +/* ----- array quantile -- output quantile for input from 0 to 1 ------- */ +static t_class *array_quantile_class; + +#define t_array_quantile t_array_rangeop + +static void *array_quantile_new(t_symbol *s, int argc, t_atom *argv) +{ + t_array_quantile *x = array_rangeop_new(array_quantile_class, s, + &argc, &argv, 1, 1, 1); + outlet_new(&x->x_tc.tc_obj, &s_float); + return (x); +} + +static void array_quantile_float(t_array_rangeop *x, t_floatarg f) +{ + char *itemp, *firstitem; + int stride, nitem, arrayonset, i; + double sum; + if (!array_rangeop_getrange(x, &firstitem, &nitem, &stride, &arrayonset)) + return; + for (i = 0, sum = 0, itemp = firstitem; i < nitem; i++, itemp += stride) + sum += (*(t_float *)itemp > 0? *(t_float *)itemp : 0); + sum *= f; + for (i = 0, itemp = firstitem; i < (nitem-1); i++, itemp += stride) + { + sum -= (*(t_float *)itemp > 0? *(t_float *)itemp : 0); + if (sum < 0) + break; + } + outlet_float(x->x_outlet, i); +} + +/* ---- array random -- output random value with array as distribution ---- */ +static t_class *array_random_class; + +typedef struct _array_random /* any operation meaningful on a subrange */ +{ + t_array_rangeop x_r; + unsigned int x_state; +} t_array_random; + +static void *array_random_new(t_symbol *s, int argc, t_atom *argv) +{ + t_array_random *x = array_rangeop_new(array_random_class, s, + &argc, &argv, 0, 1, 1); + static unsigned int random_nextseed = 584926371; + random_nextseed = random_nextseed * 435898247 + 938284287; + x->x_state = random_nextseed; + outlet_new(&x->x_r.x_tc.tc_obj, &s_float); + return (x); +} + +static void array_random_seed(t_array_random *x, t_floatarg f) +{ + x->x_state = f; +} + +static void array_random_bang(t_array_random *x) +{ + char *itemp, *firstitem; + int stride, nitem, arrayonset, i; + + if (!array_rangeop_getrange(&x->x_r, &firstitem, &nitem, &stride, + &arrayonset)) + return; + x->x_state = x->x_state * 472940017 + 832416023; + array_quantile_float(&x->x_r, (1./4294967296.0) * (double)(x->x_state)); +} + +static void array_random_float(t_array_random *x, t_floatarg f) +{ + x->x_r.x_onset = f; + array_random_bang(x); +} + +/* ---- array max -- output largest value and its index ------------ */ +static t_class *array_max_class; + +typedef struct _array_max +{ + t_array_rangeop x_rangeop; + t_outlet *x_out1; /* value */ + t_outlet *x_out2; /* index */ +} t_array_max; + +static void *array_max_new(t_symbol *s, int argc, t_atom *argv) +{ + t_array_max *x = array_rangeop_new(array_max_class, s, &argc, &argv, + 0, 1, 1); + x->x_out1 = outlet_new(&x->x_rangeop.x_tc.tc_obj, &s_float); + x->x_out2 = outlet_new(&x->x_rangeop.x_tc.tc_obj, &s_float); + return (x); +} + +static void array_max_bang(t_array_max *x) +{ + char *itemp, *firstitem; + int stride, nitem, arrayonset, i, besti; + t_float bestf; + if (!array_rangeop_getrange(&x->x_rangeop, &firstitem, &nitem, &stride, + &arrayonset)) + return; + for (i = 0, besti = -1, bestf= -1e30, itemp = firstitem; + i < nitem; i++, itemp += stride) + if (*(t_float *)itemp > bestf) + bestf = *(t_float *)itemp, besti = i+arrayonset; + outlet_float(x->x_out2, besti); + outlet_float(x->x_out1, bestf); +} + +static void array_max_float(t_array_max *x, t_floatarg f) +{ + x->x_rangeop.x_onset = f; + array_max_bang(x); +} + +/* ---- array min -- output largest value and its index ------------ */ +static t_class *array_min_class; + +typedef struct _array_min +{ + t_array_rangeop x_rangeop; + t_outlet *x_out1; /* value */ + t_outlet *x_out2; /* index */ +} t_array_min; + +static void *array_min_new(t_symbol *s, int argc, t_atom *argv) +{ + t_array_min *x = array_rangeop_new(array_min_class, s, &argc, &argv, + 0, 1, 1); + x->x_out1 = outlet_new(&x->x_rangeop.x_tc.tc_obj, &s_float); + x->x_out2 = outlet_new(&x->x_rangeop.x_tc.tc_obj, &s_float); + return (x); +} + +static void array_min_bang(t_array_min *x) +{ + char *itemp, *firstitem; + int stride, nitem, i, arrayonset, besti; + t_float bestf; + if (!array_rangeop_getrange(&x->x_rangeop, &firstitem, &nitem, &stride, + &arrayonset)) + return; + for (i = 0, besti = -1, bestf= 1e30, itemp = firstitem; + i < nitem; i++, itemp += stride) + if (*(t_float *)itemp < bestf) + bestf = *(t_float *)itemp, besti = i+arrayonset; + outlet_float(x->x_out2, besti); + outlet_float(x->x_out1, bestf); +} + +static void array_min_float(t_array_min *x, t_floatarg f) +{ + x->x_rangeop.x_onset = f; + array_min_bang(x); +} + +/* overall creator for "array" objects - dispatch to "array define" etc */ +static void *arrayobj_new(t_symbol *s, int argc, t_atom *argv) +{ + if (!argc || argv[0].a_type != A_SYMBOL) + pd_this->pd_newest = array_define_new(s, argc, argv); + else + { + char *str = argv[0].a_w.w_symbol->s_name; + if (!strcmp(str, "d") || !strcmp(str, "define")) + pd_this->pd_newest = array_define_new(s, argc-1, argv+1); + else if (!strcmp(str, "size")) + pd_this->pd_newest = array_size_new(s, argc-1, argv+1); + else if (!strcmp(str, "sum")) + pd_this->pd_newest = array_sum_new(s, argc-1, argv+1); + else if (!strcmp(str, "get")) + pd_this->pd_newest = array_get_new(s, argc-1, argv+1); + else if (!strcmp(str, "set")) + pd_this->pd_newest = array_set_new(s, argc-1, argv+1); + else if (!strcmp(str, "quantile")) + pd_this->pd_newest = array_quantile_new(s, argc-1, argv+1); + else if (!strcmp(str, "random")) + pd_this->pd_newest = array_random_new(s, argc-1, argv+1); + else if (!strcmp(str, "max")) + pd_this->pd_newest = array_max_new(s, argc-1, argv+1); + else if (!strcmp(str, "min")) + pd_this->pd_newest = array_min_new(s, argc-1, argv+1); + else + { + error("array %s: unknown function", str); + pd_this->pd_newest = 0; + } + } + return (pd_this->pd_newest); +} + +void canvas_add_for_class(t_class *c); + +/* ---------------- global setup function -------------------- */ + +void x_array_setup(void ) +{ + array_define_class = class_new(gensym("array define"), 0, + (t_method)canvas_free, sizeof(t_canvas), 0, 0); + canvas_add_for_class(array_define_class); + class_addmethod(array_define_class, (t_method)array_define_send, + gensym("send"), A_SYMBOL, 0); + class_addanything(array_define_class, array_define_anything); + class_sethelpsymbol(array_define_class, gensym("array-object")); + class_setsavefn(array_define_class, array_define_save); + + class_addmethod(array_define_class, (t_method)array_define_ignore, + gensym("editmode"), A_GIMME, 0); + + class_addcreator((t_newmethod)arrayobj_new, gensym("array"), A_GIMME, 0); + + class_addcreator((t_newmethod)table_new, gensym("table"), + A_DEFSYM, A_DEFFLOAT, 0); + + array_size_class = class_new(gensym("array size"), + (t_newmethod)array_size_new, (t_method)array_client_free, + sizeof(t_array_size), 0, A_GIMME, 0); + class_addbang(array_size_class, array_size_bang); + class_addfloat(array_size_class, array_size_float); + class_sethelpsymbol(array_size_class, gensym("array-object")); + + array_sum_class = class_new(gensym("array sum"), + (t_newmethod)array_sum_new, (t_method)array_client_free, + sizeof(t_array_sum), 0, A_GIMME, 0); + class_addbang(array_sum_class, array_sum_bang); + class_addfloat(array_sum_class, array_sum_float); + class_sethelpsymbol(array_sum_class, gensym("array-object")); + + array_get_class = class_new(gensym("array get"), + (t_newmethod)array_get_new, (t_method)array_client_free, + sizeof(t_array_get), 0, A_GIMME, 0); + class_addbang(array_get_class, array_get_bang); + class_addfloat(array_get_class, array_get_float); + class_sethelpsymbol(array_get_class, gensym("array-object")); + + array_set_class = class_new(gensym("array set"), + (t_newmethod)array_set_new, (t_method)array_client_free, + sizeof(t_array_set), 0, A_GIMME, 0); + class_addlist(array_set_class, array_set_list); + class_sethelpsymbol(array_set_class, gensym("array-object")); + + array_quantile_class = class_new(gensym("array quantile"), + (t_newmethod)array_quantile_new, (t_method)array_client_free, + sizeof(t_array_quantile), 0, A_GIMME, 0); + class_addfloat(array_quantile_class, array_quantile_float); + class_sethelpsymbol(array_quantile_class, gensym("array-object")); + + array_random_class = class_new(gensym("array random"), + (t_newmethod)array_random_new, (t_method)array_client_free, + sizeof(t_array_random), 0, A_GIMME, 0); + class_addmethod(array_random_class, (t_method)array_random_seed, + gensym("seed"), A_FLOAT, 0); + class_addfloat(array_random_class, array_random_float); + class_addbang(array_random_class, array_random_bang); + class_sethelpsymbol(array_random_class, gensym("array-object")); + + array_max_class = class_new(gensym("array max"), + (t_newmethod)array_max_new, (t_method)array_client_free, + sizeof(t_array_max), 0, A_GIMME, 0); + class_addfloat(array_max_class, array_max_float); + class_addbang(array_max_class, array_max_bang); + class_sethelpsymbol(array_max_class, gensym("array-object")); + + array_min_class = class_new(gensym("array min"), + (t_newmethod)array_min_new, (t_method)array_client_free, + sizeof(t_array_min), 0, A_GIMME, 0); + class_addfloat(array_min_class, array_min_float); + class_addbang(array_min_class, array_min_bang); + class_sethelpsymbol(array_min_class, gensym("array-object")); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/x_connective.c b/ports/camomile/source/LibPd/pure-data/src/x_connective.c new file mode 100644 index 00000000..8dca0caf --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_connective.c @@ -0,0 +1,1668 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* connective objects */ + +#include "m_pd.h" + +#include +#include +#include + +/* -------------------------- int ------------------------------ */ +static t_class *pdint_class; + +typedef struct _pdint +{ + t_object x_obj; + t_float x_f; +} t_pdint; + +static void *pdint_new(t_floatarg f) +{ + t_pdint *x = (t_pdint *)pd_new(pdint_class); + x->x_f = f; + outlet_new(&x->x_obj, &s_float); + floatinlet_new(&x->x_obj, &x->x_f); + return (x); +} + +static void pdint_bang(t_pdint *x) +{ + outlet_float(x->x_obj.ob_outlet, (t_float)(int)(x->x_f)); +} + +static void pdint_float(t_pdint *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, (t_float)(int)(x->x_f = f)); +} + +static void pdint_send(t_pdint *x, t_symbol *s) +{ + if (s->s_thing) + pd_float(s->s_thing, (t_float)(int)x->x_f); + else pd_error(x, "%s: no such object", s->s_name); +} + +void pdint_setup(void) +{ + pdint_class = class_new(gensym("int"), (t_newmethod)pdint_new, 0, + sizeof(t_pdint), 0, A_DEFFLOAT, 0); + class_addcreator((t_newmethod)pdint_new, gensym("i"), A_DEFFLOAT, 0); + class_addmethod(pdint_class, (t_method)pdint_send, gensym("send"), + A_SYMBOL, 0); + class_addbang(pdint_class, pdint_bang); + class_addfloat(pdint_class, pdint_float); +} + +/* -------------------------- float ------------------------------ */ +static t_class *pdfloat_class; + +typedef struct _pdfloat +{ + t_object x_obj; + t_float x_f; +} t_pdfloat; + + /* "float," "symbol," and "bang" are special because + they're created by short-circuited messages to the "new" + object which are handled specially in pd_typedmess(). */ + +static void *pdfloat_new(t_pd *dummy, t_float f) +{ + t_pdfloat *x = (t_pdfloat *)pd_new(pdfloat_class); + x->x_f = f; + outlet_new(&x->x_obj, &s_float); + floatinlet_new(&x->x_obj, &x->x_f); + pd_this->pd_newest = &x->x_obj.ob_pd; + return (x); +} + +static void *pdfloat_new2(t_floatarg f) +{ + return (pdfloat_new(0, f)); +} + +static void pdfloat_bang(t_pdfloat *x) +{ + outlet_float(x->x_obj.ob_outlet, x->x_f); +} + +static void pdfloat_float(t_pdfloat *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, x->x_f = f); +} + +#ifdef _MSC_VER +#define strtof(a,b) _atoldbl(a,*b) +#endif + +static void pdfloat_symbol(t_pdfloat *x, t_symbol *s) +{ + t_float f = 0.0f; + char *str_end = NULL; + f = strtof(s->s_name, &str_end); + if (f == 0 && s->s_name == str_end) + pd_error(x, "Couldn't convert %s to float.", s->s_name); + else outlet_float(x->x_obj.ob_outlet, x->x_f = f); +} + +static void pdfloat_send(t_pdfloat *x, t_symbol *s) +{ + if (s->s_thing) + pd_float(s->s_thing, x->x_f); + else pd_error(x, "%s: no such object", s->s_name); +} + +void pdfloat_setup(void) +{ + pdfloat_class = class_new(gensym("float"), (t_newmethod)pdfloat_new, 0, + sizeof(t_pdfloat), 0, A_FLOAT, 0); + class_addcreator((t_newmethod)pdfloat_new2, gensym("f"), A_DEFFLOAT, 0); + class_addmethod(pdfloat_class, (t_method)pdfloat_send, gensym("send"), + A_SYMBOL, 0); + class_addbang(pdfloat_class, pdfloat_bang); + class_addfloat(pdfloat_class, (t_method)pdfloat_float); + class_addsymbol(pdfloat_class, (t_method)pdfloat_symbol); +} + +/* -------------------------- symbol ------------------------------ */ +static t_class *pdsymbol_class; + +typedef struct _pdsymbol +{ + t_object x_obj; + t_symbol *x_s; +} t_pdsymbol; + +static void *pdsymbol_new(t_pd *dummy, t_symbol *s) +{ + t_pdsymbol *x = (t_pdsymbol *)pd_new(pdsymbol_class); + x->x_s = s; + outlet_new(&x->x_obj, &s_symbol); + symbolinlet_new(&x->x_obj, &x->x_s); + pd_this->pd_newest = &x->x_obj.ob_pd; + return (x); +} + +static void pdsymbol_bang(t_pdsymbol *x) +{ + outlet_symbol(x->x_obj.ob_outlet, x->x_s); +} + +static void pdsymbol_symbol(t_pdsymbol *x, t_symbol *s) +{ + outlet_symbol(x->x_obj.ob_outlet, x->x_s = s); +} + +static void pdsymbol_anything(t_pdsymbol *x, t_symbol *s, int ac, t_atom *av) +{ + outlet_symbol(x->x_obj.ob_outlet, x->x_s = s); +} + + /* For "list" message don't just output "list"; if empty, we want to + bang the symbol and if it starts with a symbol, we output that. + Otherwise it's not clear what we should do so we just go for the + "anything" method. LATER figure out if there are other places where + empty lists aren't equivalent to "bang"??? Should Pd's message passer + always check and call the more specific method, or should it be the + object's responsibility? Dunno... */ +static void pdsymbol_list(t_pdsymbol *x, t_symbol *s, int ac, t_atom *av) +{ + if (!ac) + pdsymbol_bang(x); + else if (av->a_type == A_SYMBOL) + pdsymbol_symbol(x, av->a_w.w_symbol); + else pdsymbol_anything(x, s, ac, av); +} + +void pdsymbol_setup(void) +{ + pdsymbol_class = class_new(gensym("symbol"), (t_newmethod)pdsymbol_new, 0, + sizeof(t_pdsymbol), 0, A_SYMBOL, 0); + class_addbang(pdsymbol_class, pdsymbol_bang); + class_addsymbol(pdsymbol_class, pdsymbol_symbol); + class_addanything(pdsymbol_class, pdsymbol_anything); +} + +/* -------------------------- bang ------------------------------ */ +static t_class *bang_class; + +typedef struct _bang +{ + t_object x_obj; +} t_bang; + +static void *bang_new(t_pd *dummy) +{ + t_bang *x = (t_bang *)pd_new(bang_class); + outlet_new(&x->x_obj, &s_bang); + pd_this->pd_newest = &x->x_obj.ob_pd; + return (x); +} + +static void *bang_new2(t_bang f) +{ + return (bang_new(0)); +} + +static void bang_bang(t_bang *x) +{ + outlet_bang(x->x_obj.ob_outlet); +} + +void bang_setup(void) +{ + bang_class = class_new(gensym("bang"), (t_newmethod)bang_new, 0, + sizeof(t_bang), 0, 0); + class_addcreator((t_newmethod)bang_new2, gensym("b"), 0); + class_addbang(bang_class, bang_bang); + class_addfloat(bang_class, bang_bang); + class_addsymbol(bang_class, bang_bang); + class_addlist(bang_class, bang_bang); + class_addanything(bang_class, bang_bang); +} + +/* -------------------- send ------------------------------ */ + +static t_class *send_class; + +typedef struct _send +{ + t_object x_obj; + t_symbol *x_sym; +} t_send; + +static void send_bang(t_send *x) +{ + if (x->x_sym->s_thing) pd_bang(x->x_sym->s_thing); +} + +static void send_float(t_send *x, t_float f) +{ + if (x->x_sym->s_thing) pd_float(x->x_sym->s_thing, f); +} + +static void send_symbol(t_send *x, t_symbol *s) +{ + if (x->x_sym->s_thing) pd_symbol(x->x_sym->s_thing, s); +} + +static void send_pointer(t_send *x, t_gpointer *gp) +{ + if (x->x_sym->s_thing) pd_pointer(x->x_sym->s_thing, gp); +} + +static void send_list(t_send *x, t_symbol *s, int argc, t_atom *argv) +{ + if (x->x_sym->s_thing) pd_list(x->x_sym->s_thing, s, argc, argv); +} + +static void send_anything(t_send *x, t_symbol *s, int argc, t_atom *argv) +{ + if (x->x_sym->s_thing) typedmess(x->x_sym->s_thing, s, argc, argv); +} + +static void *send_new(t_symbol *s) +{ + t_send *x = (t_send *)pd_new(send_class); + if (!*s->s_name) + symbolinlet_new(&x->x_obj, &x->x_sym); + x->x_sym = s; + return (x); +} + +static void send_setup(void) +{ + send_class = class_new(gensym("send"), (t_newmethod)send_new, 0, + sizeof(t_send), 0, A_DEFSYM, 0); + class_addcreator((t_newmethod)send_new, gensym("s"), A_DEFSYM, 0); + class_addbang(send_class, send_bang); + class_addfloat(send_class, send_float); + class_addsymbol(send_class, send_symbol); + class_addpointer(send_class, send_pointer); + class_addlist(send_class, send_list); + class_addanything(send_class, send_anything); +} +/* -------------------- receive ------------------------------ */ + +static t_class *receive_class; + +typedef struct _receive +{ + t_object x_obj; + t_symbol *x_sym; +} t_receive; + +static void receive_bang(t_receive *x) +{ + outlet_bang(x->x_obj.ob_outlet); +} + +static void receive_float(t_receive *x, t_float f) +{ + outlet_float(x->x_obj.ob_outlet, f); +} + +static void receive_symbol(t_receive *x, t_symbol *s) +{ + outlet_symbol(x->x_obj.ob_outlet, s); +} + +static void receive_pointer(t_receive *x, t_gpointer *gp) +{ + outlet_pointer(x->x_obj.ob_outlet, gp); +} + +static void receive_list(t_receive *x, t_symbol *s, int argc, t_atom *argv) +{ + outlet_list(x->x_obj.ob_outlet, s, argc, argv); +} + +static void receive_anything(t_receive *x, t_symbol *s, int argc, t_atom *argv) +{ + outlet_anything(x->x_obj.ob_outlet, s, argc, argv); +} + +static void *receive_new(t_symbol *s) +{ + t_receive *x = (t_receive *)pd_new(receive_class); + x->x_sym = s; + pd_bind(&x->x_obj.ob_pd, s); + outlet_new(&x->x_obj, 0); + return (x); +} + +static void receive_free(t_receive *x) +{ + pd_unbind(&x->x_obj.ob_pd, x->x_sym); +} + +static void receive_setup(void) +{ + receive_class = class_new(gensym("receive"), (t_newmethod)receive_new, + (t_method)receive_free, sizeof(t_receive), CLASS_NOINLET, A_DEFSYM, 0); + class_addcreator((t_newmethod)receive_new, gensym("r"), A_DEFSYM, 0); + class_addbang(receive_class, receive_bang); + class_addfloat(receive_class, (t_method)receive_float); + class_addsymbol(receive_class, receive_symbol); + class_addpointer(receive_class, receive_pointer); + class_addlist(receive_class, receive_list); + class_addanything(receive_class, receive_anything); +} + +/* -------------------------- select ------------------------------ */ + +static t_class *sel1_class; + +typedef struct _sel1 +{ + t_object x_obj; + t_atom x_atom; + t_outlet *x_outlet1; + t_outlet *x_outlet2; +} t_sel1; + +static void sel1_float(t_sel1 *x, t_float f) +{ + if (x->x_atom.a_type == A_FLOAT && f == x->x_atom.a_w.w_float) + outlet_bang(x->x_outlet1); + else outlet_float(x->x_outlet2, f); +} + +static void sel1_symbol(t_sel1 *x, t_symbol *s) +{ + if (x->x_atom.a_type == A_SYMBOL && s == x->x_atom.a_w.w_symbol) + outlet_bang(x->x_outlet1); + else outlet_symbol(x->x_outlet2, s); +} + +static t_class *sel2_class; + +typedef struct _selectelement +{ + t_word e_w; + t_outlet *e_outlet; +} t_selectelement; + +typedef struct _sel2 +{ + t_object x_obj; + t_atomtype x_type; + t_int x_nelement; + t_selectelement *x_vec; + t_outlet *x_rejectout; +} t_sel2; + +static void sel2_float(t_sel2 *x, t_float f) +{ + t_selectelement *e; + int nelement; + if (x->x_type == A_FLOAT) + { + for (nelement = (int)x->x_nelement, e = x->x_vec; nelement--; e++) + if (e->e_w.w_float == f) + { + outlet_bang(e->e_outlet); + return; + } + } + outlet_float(x->x_rejectout, f); +} + +static void sel2_symbol(t_sel2 *x, t_symbol *s) +{ + t_selectelement *e; + int nelement; + if (x->x_type == A_SYMBOL) + { + for (nelement = (int)x->x_nelement, e = x->x_vec; nelement--; e++) + if (e->e_w.w_symbol == s) + { + outlet_bang(e->e_outlet); + return; + } + } + outlet_symbol(x->x_rejectout, s); +} + +static void sel2_free(t_sel2 *x) +{ + freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec)); +} + +static void *select_new(t_symbol *s, int argc, t_atom *argv) +{ + t_atom a; + if (argc == 0) + { + argc = 1; + SETFLOAT(&a, 0); + argv = &a; + } + if (argc == 1) + { + t_sel1 *x = (t_sel1 *)pd_new(sel1_class); + x->x_atom = *argv; + x->x_outlet1 = outlet_new(&x->x_obj, &s_bang); + if (argv->a_type == A_FLOAT) + { + floatinlet_new(&x->x_obj, &x->x_atom.a_w.w_float); + x->x_outlet2 = outlet_new(&x->x_obj, &s_float); + } + else + { + symbolinlet_new(&x->x_obj, &x->x_atom.a_w.w_symbol); + x->x_outlet2 = outlet_new(&x->x_obj, &s_symbol); + } + return (x); + } + else + { + int n; + t_selectelement *e; + t_sel2 *x = (t_sel2 *)pd_new(sel2_class); + x->x_nelement = argc; + x->x_vec = (t_selectelement *)getbytes(argc * sizeof(*x->x_vec)); + x->x_type = argv[0].a_type; + for (n = 0, e = x->x_vec; n < argc; n++, e++) + { + e->e_outlet = outlet_new(&x->x_obj, &s_bang); + if ((x->x_type = argv->a_type) == A_FLOAT) + e->e_w.w_float = atom_getfloatarg(n, argc, argv); + else e->e_w.w_symbol = atom_getsymbolarg(n, argc, argv); + } + x->x_rejectout = outlet_new(&x->x_obj, &s_float); + return (x); + } + +} + +void select_setup(void) +{ + sel1_class = class_new(gensym("select"), 0, 0, + sizeof(t_sel1), 0, 0); + class_addfloat(sel1_class, sel1_float); + class_addsymbol(sel1_class, sel1_symbol); + + sel2_class = class_new(gensym("select"), 0, (t_method)sel2_free, + sizeof(t_sel2), 0, 0); + class_addfloat(sel2_class, sel2_float); + class_addsymbol(sel2_class, sel2_symbol); + + class_addcreator((t_newmethod)select_new, gensym("select"), A_GIMME, 0); + class_addcreator((t_newmethod)select_new, gensym("sel"), A_GIMME, 0); +} + +/* -------------------------- route ------------------------------ */ + +static t_class *route_class; + +typedef struct _routeelement +{ + t_word e_w; + t_outlet *e_outlet; +} t_routeelement; + +typedef struct _route +{ + t_object x_obj; + t_atomtype x_type; + t_int x_nelement; + t_routeelement *x_vec; + t_outlet *x_rejectout; +} t_route; + +static void route_anything(t_route *x, t_symbol *sel, int argc, t_atom *argv) +{ + t_routeelement *e; + int nelement; + if (x->x_type == A_SYMBOL) + { + for (nelement = (int)x->x_nelement, e = x->x_vec; nelement--; e++) + if (e->e_w.w_symbol == sel) + { + if (argc > 0 && argv[0].a_type == A_SYMBOL) + outlet_anything(e->e_outlet, argv[0].a_w.w_symbol, + argc-1, argv+1); + else outlet_list(e->e_outlet, 0, argc, argv); + return; + } + } + outlet_anything(x->x_rejectout, sel, argc, argv); +} + +static void route_list(t_route *x, t_symbol *sel, int argc, t_atom *argv) +{ + t_routeelement *e; + int nelement; + if (x->x_type == A_FLOAT) + { + t_float f; + if (!argc) return; + if (argv->a_type != A_FLOAT) + goto rejected; + f = atom_getfloat(argv); + for (nelement = (int)x->x_nelement, e = x->x_vec; nelement--; e++) + if (e->e_w.w_float == f) + { + if (argc > 1 && argv[1].a_type == A_SYMBOL) + outlet_anything(e->e_outlet, argv[1].a_w.w_symbol, + argc-2, argv+2); + else outlet_list(e->e_outlet, 0, argc-1, argv+1); + return; + } + } + else /* symbol arguments */ + { + if (argc > 1) /* 2 or more args: treat as "list" */ + { + for (nelement = (int)x->x_nelement, e = x->x_vec; nelement--; e++) + { + if (e->e_w.w_symbol == &s_list) + { + if (argc > 0 && argv[0].a_type == A_SYMBOL) + outlet_anything(e->e_outlet, argv[0].a_w.w_symbol, + argc-1, argv+1); + else outlet_list(e->e_outlet, 0, argc, argv); + return; + } + } + } + else if (argc == 0) /* no args: treat as "bang" */ + { + for (nelement = (int)x->x_nelement, e = x->x_vec; nelement--; e++) + { + if (e->e_w.w_symbol == &s_bang) + { + outlet_bang(e->e_outlet); + return; + } + } + } + else if (argv[0].a_type == A_FLOAT) /* one float arg */ + { + for (nelement = (int)x->x_nelement, e = x->x_vec; nelement--; e++) + { + if (e->e_w.w_symbol == &s_float) + { + outlet_float(e->e_outlet, argv[0].a_w.w_float); + return; + } + } + } + else + { + for (nelement = (int)x->x_nelement, e = x->x_vec; nelement--; e++) + { + if (e->e_w.w_symbol == &s_symbol) + { + outlet_symbol(e->e_outlet, argv[0].a_w.w_symbol); + return; + } + } + } + } + rejected: + outlet_list(x->x_rejectout, 0, argc, argv); +} + + +static void route_free(t_route *x) +{ + freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec)); +} + +static void *route_new(t_symbol *s, int argc, t_atom *argv) +{ + int n; + t_routeelement *e; + t_route *x = (t_route *)pd_new(route_class); + t_atom a; + if (argc == 0) + { + argc = 1; + SETFLOAT(&a, 0); + argv = &a; + } + x->x_type = argv[0].a_type; + x->x_nelement = argc; + x->x_vec = (t_routeelement *)getbytes(argc * sizeof(*x->x_vec)); + for (n = 0, e = x->x_vec; n < argc; n++, e++) + { + e->e_outlet = outlet_new(&x->x_obj, &s_list); + if (x->x_type == A_FLOAT) + e->e_w.w_float = atom_getfloatarg(n, argc, argv); + else e->e_w.w_symbol = atom_getsymbolarg(n, argc, argv); + } + if (argc == 1) + { + if (argv->a_type == A_FLOAT) + floatinlet_new(&x->x_obj, &x->x_vec->e_w.w_float); + else symbolinlet_new(&x->x_obj, &x->x_vec->e_w.w_symbol); + } + x->x_rejectout = outlet_new(&x->x_obj, &s_list); + return (x); +} + +void route_setup(void) +{ + route_class = class_new(gensym("route"), (t_newmethod)route_new, + (t_method)route_free, sizeof(t_route), 0, A_GIMME, 0); + class_addlist(route_class, route_list); + class_addanything(route_class, route_anything); +} + +/* -------------------------- pack ------------------------------ */ + +static t_class *pack_class; + +typedef struct _pack +{ + t_object x_obj; + t_int x_n; /* number of args */ + t_atom *x_vec; /* input values */ + t_int x_nptr; /* number of pointers */ + t_gpointer *x_gpointer; /* the pointers */ + t_atom *x_outvec; /* space for output values */ +} t_pack; + +static void *pack_new(t_symbol *s, int argc, t_atom *argv) +{ + t_pack *x = (t_pack *)pd_new(pack_class); + t_atom defarg[2], *ap, *vec, *vp; + t_gpointer *gp; + int nptr = 0; + int i; + if (!argc) + { + argv = defarg; + argc = 2; + SETFLOAT(&defarg[0], 0); + SETFLOAT(&defarg[1], 0); + } + + x->x_n = argc; + vec = x->x_vec = (t_atom *)getbytes(argc * sizeof(*x->x_vec)); + x->x_outvec = (t_atom *)getbytes(argc * sizeof(*x->x_outvec)); + + for (i = argc, ap = argv; i--; ap++) + if (ap->a_type == A_SYMBOL && *ap->a_w.w_symbol->s_name == 'p') + nptr++; + + gp = x->x_gpointer = (t_gpointer *)t_getbytes(nptr * sizeof (*gp)); + x->x_nptr = nptr; + + for (i = 0, vp = x->x_vec, ap = argv; i < argc; i++, ap++, vp++) + { + if (ap->a_type == A_FLOAT) + { + *vp = *ap; + if (i) floatinlet_new(&x->x_obj, &vp->a_w.w_float); + } + else if (ap->a_type == A_SYMBOL) + { + char c = *ap->a_w.w_symbol->s_name; + if (c == 's') + { + SETSYMBOL(vp, &s_symbol); + if (i) symbolinlet_new(&x->x_obj, &vp->a_w.w_symbol); + } + else if (c == 'p') + { + vp->a_type = A_POINTER; + vp->a_w.w_gpointer = gp; + gpointer_init(gp); + if (i) pointerinlet_new(&x->x_obj, gp); + gp++; + } + else + { + if (c != 'f') pd_error(x, "pack: %s: bad type", + ap->a_w.w_symbol->s_name); + SETFLOAT(vp, 0); + if (i) floatinlet_new(&x->x_obj, &vp->a_w.w_float); + } + } + } + outlet_new(&x->x_obj, &s_list); + return (x); +} + +static void pack_bang(t_pack *x) +{ + int i, reentered = 0, size = (int)(x->x_n * sizeof(t_atom)); + t_gpointer *gp; + t_atom *outvec; + for (i = (int)x->x_nptr, gp = x->x_gpointer; i--; gp++) + if (!gpointer_check(gp, 1)) + { + pd_error(x, "pack: stale pointer"); + return; + } + /* reentrancy protection. The first time through use the pre-allocated + x_outvec; if we're reentered we have to allocate new memory. */ + if (!x->x_outvec) + { + /* LATER figure out how to deal with reentrancy and pointers... */ + if (x->x_nptr) + post("pack_bang: warning: reentry with pointers unprotected"); + outvec = t_getbytes(size); + reentered = 1; + } + else + { + outvec = x->x_outvec; + x->x_outvec = 0; + } + memcpy(outvec, x->x_vec, size); + outlet_list(x->x_obj.ob_outlet, &s_list, (int)x->x_n, outvec); + if (reentered) + t_freebytes(outvec, size); + else x->x_outvec = outvec; +} + +static void pack_pointer(t_pack *x, t_gpointer *gp) +{ + if (x->x_vec->a_type == A_POINTER) + { + gpointer_unset(x->x_gpointer); + *x->x_gpointer = *gp; + if (gp->gp_stub) gp->gp_stub->gs_refcount++; + pack_bang(x); + } + else pd_error(x, "pack_pointer: wrong type"); +} + +static void pack_float(t_pack *x, t_float f) +{ + if (x->x_vec->a_type == A_FLOAT) + { + x->x_vec->a_w.w_float = f; + pack_bang(x); + } + else pd_error(x, "pack_float: wrong type"); +} + +static void pack_symbol(t_pack *x, t_symbol *s) +{ + if (x->x_vec->a_type == A_SYMBOL) + { + x->x_vec->a_w.w_symbol = s; + pack_bang(x); + } + else pd_error(x, "pack_symbol: wrong type"); +} + +static void pack_list(t_pack *x, t_symbol *s, int ac, t_atom *av) +{ + obj_list(&x->x_obj, 0, ac, av); +} + +static void pack_anything(t_pack *x, t_symbol *s, int ac, t_atom *av) +{ + t_atom *av2 = (t_atom *)getbytes((ac + 1) * sizeof(t_atom)); + int i; + for (i = 0; i < ac; i++) + av2[i + 1] = av[i]; + SETSYMBOL(av2, s); + obj_list(&x->x_obj, 0, ac+1, av2); + freebytes(av2, (ac + 1) * sizeof(t_atom)); +} + +static void pack_free(t_pack *x) +{ + t_gpointer *gp; + int i; + for (gp = x->x_gpointer, i = (int)x->x_nptr; i--; gp++) + gpointer_unset(gp); + freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec)); + freebytes(x->x_outvec, x->x_n * sizeof(*x->x_outvec)); + freebytes(x->x_gpointer, x->x_nptr * sizeof(*x->x_gpointer)); +} + +static void pack_setup(void) +{ + pack_class = class_new(gensym("pack"), (t_newmethod)pack_new, + (t_method)pack_free, sizeof(t_pack), 0, A_GIMME, 0); + class_addbang(pack_class, pack_bang); + class_addpointer(pack_class, pack_pointer); + class_addfloat(pack_class, pack_float); + class_addsymbol(pack_class, pack_symbol); + class_addlist(pack_class, pack_list); + class_addanything(pack_class, pack_anything); +} + +/* -------------------------- unpack ------------------------------ */ + +static t_class *unpack_class; + +typedef struct unpackout +{ + t_atomtype u_type; + t_outlet *u_outlet; +} t_unpackout; + +typedef struct _unpack +{ + t_object x_obj; + t_int x_n; + t_unpackout *x_vec; +} t_unpack; + +static void *unpack_new(t_symbol *s, int argc, t_atom *argv) +{ + t_unpack *x = (t_unpack *)pd_new(unpack_class); + t_atom defarg[2], *ap; + t_unpackout *u; + int i; + if (!argc) + { + argv = defarg; + argc = 2; + SETFLOAT(&defarg[0], 0); + SETFLOAT(&defarg[1], 0); + } + x->x_n = argc; + x->x_vec = (t_unpackout *)getbytes(argc * sizeof(*x->x_vec)); + for (i = 0, ap = argv, u = x->x_vec; i < argc; u++, ap++, i++) + { + t_atomtype type = ap->a_type; + if (type == A_SYMBOL) + { + char c = *ap->a_w.w_symbol->s_name; + if (c == 's') + { + u->u_type = A_SYMBOL; + u->u_outlet = outlet_new(&x->x_obj, &s_symbol); + } + else if (c == 'p') + { + u->u_type = A_POINTER; + u->u_outlet = outlet_new(&x->x_obj, &s_pointer); + } + else + { + if (c != 'f') pd_error(x, "unpack: %s: bad type", + ap->a_w.w_symbol->s_name); + u->u_type = A_FLOAT; + u->u_outlet = outlet_new(&x->x_obj, &s_float); + } + } + else + { + u->u_type = A_FLOAT; + u->u_outlet = outlet_new(&x->x_obj, &s_float); + } + } + return (x); +} + +static void unpack_list(t_unpack *x, t_symbol *s, int argc, t_atom *argv) +{ + t_atom *ap; + t_unpackout *u; + int i; + if (argc > x->x_n) argc = (int)x->x_n; + for (i = argc, u = x->x_vec + i, ap = argv + i; u--, ap--, i--;) + { + t_atomtype type = u->u_type; + if (type != ap->a_type) + pd_error(x, "unpack: type mismatch"); + else if (type == A_FLOAT) + outlet_float(u->u_outlet, ap->a_w.w_float); + else if (type == A_SYMBOL) + outlet_symbol(u->u_outlet, ap->a_w.w_symbol); + else outlet_pointer(u->u_outlet, ap->a_w.w_gpointer); + } +} + +static void unpack_anything(t_unpack *x, t_symbol *s, int ac, t_atom *av) +{ + t_atom *av2 = (t_atom *)getbytes((ac + 1) * sizeof(t_atom)); + int i; + for (i = 0; i < ac; i++) + av2[i + 1] = av[i]; + SETSYMBOL(av2, s); + unpack_list(x, 0, ac+1, av2); + freebytes(av2, (ac + 1) * sizeof(t_atom)); +} + +static void unpack_free(t_unpack *x) +{ + freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec)); +} + +static void unpack_setup(void) +{ + unpack_class = class_new(gensym("unpack"), (t_newmethod)unpack_new, + (t_method)unpack_free, sizeof(t_unpack), 0, A_GIMME, 0); + class_addlist(unpack_class, unpack_list); + class_addanything(unpack_class, unpack_anything); +} + +/* -------------------------- trigger ------------------------------ */ + +static t_class *trigger_class; +#define TR_BANG 0 +#define TR_FLOAT 1 +#define TR_SYMBOL 2 +#define TR_POINTER 3 +#define TR_LIST 4 +#define TR_ANYTHING 5 + +typedef struct triggerout +{ + int u_type; /* outlet type from above */ + t_outlet *u_outlet; +} t_triggerout; + +typedef struct _trigger +{ + t_object x_obj; + t_int x_n; + t_triggerout *x_vec; +} t_trigger; + +static void *trigger_new(t_symbol *s, int argc, t_atom *argv) +{ + t_trigger *x = (t_trigger *)pd_new(trigger_class); + t_atom defarg[2], *ap; + t_triggerout *u; + int i; + if (!argc) + { + argv = defarg; + argc = 2; + SETSYMBOL(&defarg[0], &s_bang); + SETSYMBOL(&defarg[1], &s_bang); + } + x->x_n = argc; + x->x_vec = (t_triggerout *)getbytes(argc * sizeof(*x->x_vec)); + for (i = 0, ap = argv, u = x->x_vec; i < argc; u++, ap++, i++) + { + t_atomtype thistype = ap->a_type; + char c; + if (thistype == TR_SYMBOL) c = ap->a_w.w_symbol->s_name[0]; + else if (thistype == TR_FLOAT) c = 'f'; + else c = 0; + if (c == 'p') + u->u_type = TR_POINTER, + u->u_outlet = outlet_new(&x->x_obj, &s_pointer); + else if (c == 'f') + u->u_type = TR_FLOAT, u->u_outlet = outlet_new(&x->x_obj, &s_float); + else if (c == 'b') + u->u_type = TR_BANG, u->u_outlet = outlet_new(&x->x_obj, &s_bang); + else if (c == 'l') + u->u_type = TR_LIST, u->u_outlet = outlet_new(&x->x_obj, &s_list); + else if (c == 's') + u->u_type = TR_SYMBOL, + u->u_outlet = outlet_new(&x->x_obj, &s_symbol); + else if (c == 'a') + u->u_type = TR_ANYTHING, + u->u_outlet = outlet_new(&x->x_obj, &s_symbol); + else + { + pd_error(x, "trigger: %s: bad type", ap->a_w.w_symbol->s_name); + u->u_type = TR_FLOAT, u->u_outlet = outlet_new(&x->x_obj, &s_float); + } + } + return (x); +} + +static void trigger_list(t_trigger *x, t_symbol *s, int argc, t_atom *argv) +{ + t_triggerout *u; + int i; + for (i = (int)x->x_n, u = x->x_vec + i; u--, i--;) + { + if (u->u_type == TR_FLOAT) + outlet_float(u->u_outlet, (argc ? atom_getfloat(argv) : 0)); + else if (u->u_type == TR_BANG) + outlet_bang(u->u_outlet); + else if (u->u_type == TR_SYMBOL) + outlet_symbol(u->u_outlet, + (argc ? atom_getsymbol(argv) : &s_symbol)); + else if (u->u_type == TR_POINTER) + { + if (!argc || argv->a_type != TR_POINTER) + pd_error(x, "unpack: bad pointer"); + else outlet_pointer(u->u_outlet, argv->a_w.w_gpointer); + } + else outlet_list(u->u_outlet, &s_list, argc, argv); + } +} + +static void trigger_anything(t_trigger *x, t_symbol *s, int argc, t_atom *argv) +{ + t_triggerout *u; + int i; + for (i = (int)x->x_n, u = x->x_vec + i; u--, i--;) + { + if (u->u_type == TR_BANG) + outlet_bang(u->u_outlet); + else if (u->u_type == TR_ANYTHING) + outlet_anything(u->u_outlet, s, argc, argv); + else pd_error(x, "trigger: can only convert 's' to 'b' or 'a'"); + } +} + +static void trigger_bang(t_trigger *x) +{ + trigger_list(x, 0, 0, 0); +} + +static void trigger_pointer(t_trigger *x, t_gpointer *gp) +{ + t_atom at; + SETPOINTER(&at, gp); + trigger_list(x, 0, 1, &at); +} + +static void trigger_float(t_trigger *x, t_float f) +{ + t_atom at; + SETFLOAT(&at, f); + trigger_list(x, 0, 1, &at); +} + +static void trigger_symbol(t_trigger *x, t_symbol *s) +{ + t_atom at; + SETSYMBOL(&at, s); + trigger_list(x, 0, 1, &at); +} + +static void trigger_free(t_trigger *x) +{ + freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec)); +} + +static void trigger_setup(void) +{ + trigger_class = class_new(gensym("trigger"), (t_newmethod)trigger_new, + (t_method)trigger_free, sizeof(t_trigger), 0, A_GIMME, 0); + class_addcreator((t_newmethod)trigger_new, gensym("t"), A_GIMME, 0); + class_addlist(trigger_class, trigger_list); + class_addbang(trigger_class, trigger_bang); + class_addpointer(trigger_class, trigger_pointer); + class_addfloat(trigger_class, (t_method)trigger_float); + class_addsymbol(trigger_class, trigger_symbol); + class_addanything(trigger_class, trigger_anything); +} + +/* -------------------------- spigot ------------------------------ */ +static t_class *spigot_class; + +typedef struct _spigot +{ + t_object x_obj; + t_float x_state; +} t_spigot; + +static void *spigot_new(t_floatarg f) +{ + t_spigot *x = (t_spigot *)pd_new(spigot_class); + floatinlet_new(&x->x_obj, &x->x_state); + outlet_new(&x->x_obj, 0); + x->x_state = f; + return (x); +} + +static void spigot_bang(t_spigot *x) +{ + if (x->x_state != 0) outlet_bang(x->x_obj.ob_outlet); +} + +static void spigot_pointer(t_spigot *x, t_gpointer *gp) +{ + if (x->x_state != 0) outlet_pointer(x->x_obj.ob_outlet, gp); +} + +static void spigot_float(t_spigot *x, t_float f) +{ + if (x->x_state != 0) outlet_float(x->x_obj.ob_outlet, f); +} + +static void spigot_symbol(t_spigot *x, t_symbol *s) +{ + if (x->x_state != 0) outlet_symbol(x->x_obj.ob_outlet, s); +} + +static void spigot_list(t_spigot *x, t_symbol *s, int argc, t_atom *argv) +{ + if (x->x_state != 0) outlet_list(x->x_obj.ob_outlet, s, argc, argv); +} + +static void spigot_anything(t_spigot *x, t_symbol *s, int argc, t_atom *argv) +{ + if (x->x_state != 0) outlet_anything(x->x_obj.ob_outlet, s, argc, argv); +} + +static void spigot_setup(void) +{ + spigot_class = class_new(gensym("spigot"), (t_newmethod)spigot_new, 0, + sizeof(t_spigot), 0, A_DEFFLOAT, 0); + class_addbang(spigot_class, spigot_bang); + class_addpointer(spigot_class, spigot_pointer); + class_addfloat(spigot_class, spigot_float); + class_addsymbol(spigot_class, spigot_symbol); + class_addlist(spigot_class, spigot_list); + class_addanything(spigot_class, spigot_anything); +} + +/* --------------------------- moses ----------------------------- */ +static t_class *moses_class; + +typedef struct _moses +{ + t_object x_ob; + t_outlet *x_out2; + t_float x_y; +} t_moses; + +static void *moses_new(t_floatarg f) +{ + t_moses *x = (t_moses *)pd_new(moses_class); + floatinlet_new(&x->x_ob, &x->x_y); + outlet_new(&x->x_ob, &s_float); + x->x_out2 = outlet_new(&x->x_ob, &s_float); + x->x_y = f; + return (x); +} + +static void moses_float(t_moses *x, t_float f) +{ + if (f < x->x_y) outlet_float(x->x_ob.ob_outlet, f); + else outlet_float(x->x_out2, f); +} + +static void moses_setup(void) +{ + moses_class = class_new(gensym("moses"), (t_newmethod)moses_new, 0, + sizeof(t_moses), 0, A_DEFFLOAT, 0); + class_addfloat(moses_class, moses_float); +} + +/* ----------------------- until --------------------- */ + +static t_class *until_class; + +typedef struct _until +{ + t_object x_obj; + int x_run; + int x_count; +} t_until; + +static void *until_new(void) +{ + t_until *x = (t_until *)pd_new(until_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("bang"), gensym("bang2")); + outlet_new(&x->x_obj, &s_bang); + x->x_run = 0; + return (x); +} + +static void until_bang(t_until *x) +{ + x->x_run = 1; + x->x_count = -1; + while (x->x_run && x->x_count) + x->x_count--, outlet_bang(x->x_obj.ob_outlet); +} + +static void until_float(t_until *x, t_float f) +{ + if (f < 0) + f = 0; + x->x_run = 1; + x->x_count = f; + while (x->x_run && x->x_count) + x->x_count--, outlet_bang(x->x_obj.ob_outlet); +} + +static void until_bang2(t_until *x) +{ + x->x_run = 0; +} + +static void until_setup(void) +{ + until_class = class_new(gensym("until"), (t_newmethod)until_new, 0, + sizeof(t_until), 0, 0); + class_addbang(until_class, until_bang); + class_addfloat(until_class, until_float); + class_addmethod(until_class, (t_method)until_bang2, gensym("bang2"), 0); +} + +/* ----------------------- makefilename --------------------- */ + +static t_class *makefilename_class; + +typedef enum { + NONE = 0, + INT, + FLOAT, + STRING, + POINTER, +} t_printtype; + +typedef struct _makefilename +{ + t_object x_obj; + t_symbol *x_format; + t_printtype x_accept; +} t_makefilename; + +static const char* _formatscan(const char*str, t_printtype*typ) { + int num=0, infmt=0; + for (; *str; str++) { + if (!infmt && *str=='%') { + infmt=1; + continue; + } + if (infmt) { + if (*str=='%') { + infmt=0; + continue; + } + if (strchr("-.#0123456789",*str)!=0) + continue; + if (*str=='s') { + *typ = STRING; + return str; + } + if (strchr("fgGeE",*str)!=0) { + *typ = FLOAT; + return str; + } + if (strchr("xXdiouc",*str)!=0) { + *typ = INT; + return str; + } + if (strchr("p",*str)!=0) { + *typ = POINTER; + return str; + } + } + } + *typ = NONE; + return str; +} + +static void makefilename_scanformat(t_makefilename *x) +{ + int num=0, infmt=0; + const char *str; + char *chr; + t_printtype typ; + if (!x->x_format) return; + str = x->x_format->s_name; + str = _formatscan(str, &typ); + x->x_accept = typ; + if (str && (NONE != typ)) { + /* try again, to see if there's another format specifier (which we forbid) */ + str = _formatscan(str, &typ); + if (NONE != typ) { + pd_error(x, "makefilename: invalid format string '%s' (too many format specifiers)", x->x_format->s_name); + x->x_format = 0; + return; + } + } +} + +static void *makefilename_new(t_symbol *s) +{ + t_makefilename *x = (t_makefilename *)pd_new(makefilename_class); + if (!s || !*s->s_name) + s = gensym("file.%d"); + outlet_new(&x->x_obj, &s_symbol); + x->x_format = s; + x->x_accept = NONE; + makefilename_scanformat(x); + return (x); +} + +static void makefilename_float(t_makefilename *x, t_floatarg f) +{ + char buf[MAXPDSTRING]; + if(!x->x_format) { + pd_error(x, "makefilename: no format specifier given"); + return; + } + switch(x->x_accept) { + case NONE: + sprintf(buf, "%s", x->x_format->s_name); + break; + case INT: case POINTER: + sprintf(buf, x->x_format->s_name, (int)f); + break; + case FLOAT: + sprintf(buf, x->x_format->s_name, f); + break; + case STRING: { + char buf2[MAXPDSTRING]; + sprintf(buf2, "%g", f); + sprintf(buf, x->x_format->s_name, buf2); + break; + } + default: + sprintf(buf, "%s", x->x_format->s_name); + } + if (buf[0]!=0) + outlet_symbol(x->x_obj.ob_outlet, gensym(buf)); +} + +static void makefilename_symbol(t_makefilename *x, t_symbol *s) +{ + char buf[MAXPDSTRING]; + if(!x->x_format) { + pd_error(x, "makefilename: no format specifier given"); + return; + } + switch(x->x_accept) { + case STRING: case POINTER: + sprintf(buf, x->x_format->s_name, s->s_name); + break; + case INT: + sprintf(buf, x->x_format->s_name, 0); + break; + case FLOAT: + sprintf(buf, x->x_format->s_name, 0.); + break; + case NONE: + sprintf(buf, "%s", x->x_format->s_name); + break; + default: + sprintf(buf, "%s", x->x_format->s_name); + } + if (buf[0]!=0) + outlet_symbol(x->x_obj.ob_outlet, gensym(buf)); +} + +static void makefilename_bang(t_makefilename *x) +{ + char buf[MAXPDSTRING]; + if(!x->x_format) { + pd_error(x, "makefilename: no format specifier given"); + return; + } + switch(x->x_accept) { + case INT: + sprintf(buf, x->x_format->s_name, 0); + break; + case FLOAT: + sprintf(buf, x->x_format->s_name, 0.); + break; + case NONE: + sprintf(buf, "%s", x->x_format->s_name); + break; + default: + sprintf(buf, "%s", x->x_format->s_name); + } + if (buf[0]!=0) + outlet_symbol(x->x_obj.ob_outlet, gensym(buf)); +} + +static void makefilename_set(t_makefilename *x, t_symbol *s) +{ + x->x_format = s; + makefilename_scanformat(x); +} + +static void makefilename_setup(void) +{ + makefilename_class = class_new(gensym("makefilename"), + (t_newmethod)makefilename_new, 0, + sizeof(t_makefilename), 0, A_DEFSYM, 0); + class_addfloat(makefilename_class, makefilename_float); + class_addsymbol(makefilename_class, makefilename_symbol); + class_addbang(makefilename_class, makefilename_bang); + class_addmethod(makefilename_class, (t_method)makefilename_set, + gensym("set"), A_SYMBOL, 0); +} + +/* -------------------------- swap ------------------------------ */ +static t_class *swap_class; + +typedef struct _swap +{ + t_object x_obj; + t_outlet *x_out2; + t_float x_f1; + t_float x_f2; +} t_swap; + +static void *swap_new(t_floatarg f) +{ + t_swap *x = (t_swap *)pd_new(swap_class); + x->x_f2 = f; + x->x_f1 = 0; + outlet_new(&x->x_obj, &s_float); + x->x_out2 = outlet_new(&x->x_obj, &s_float); + floatinlet_new(&x->x_obj, &x->x_f2); + return (x); +} + +static void swap_bang(t_swap *x) +{ + outlet_float(x->x_out2, x->x_f1); + outlet_float(x->x_obj.ob_outlet, x->x_f2); +} + +static void swap_float(t_swap *x, t_float f) +{ + x->x_f1 = f; + swap_bang(x); +} + +void swap_setup(void) +{ + swap_class = class_new(gensym("swap"), (t_newmethod)swap_new, 0, + sizeof(t_swap), 0, A_DEFFLOAT, 0); + class_addcreator((t_newmethod)swap_new, gensym("fswap"), A_DEFFLOAT, 0); + class_addbang(swap_class, swap_bang); + class_addfloat(swap_class, swap_float); +} + +/* -------------------------- change ------------------------------ */ +static t_class *change_class; + +typedef struct _change +{ + t_object x_obj; + t_float x_f; +} t_change; + +static void *change_new(t_floatarg f) +{ + t_change *x = (t_change *)pd_new(change_class); + x->x_f = f; + outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void change_bang(t_change *x) +{ + outlet_float(x->x_obj.ob_outlet, x->x_f); +} + +static void change_float(t_change *x, t_float f) +{ + if (f != x->x_f) + { + x->x_f = f; + outlet_float(x->x_obj.ob_outlet, x->x_f); + } +} + +static void change_set(t_change *x, t_float f) +{ + x->x_f = f; +} + +void change_setup(void) +{ + change_class = class_new(gensym("change"), (t_newmethod)change_new, 0, + sizeof(t_change), 0, A_DEFFLOAT, 0); + class_addbang(change_class, change_bang); + class_addfloat(change_class, change_float); + class_addmethod(change_class, (t_method)change_set, gensym("set"), + A_DEFFLOAT, 0); +} + +/* -------------------- value ------------------------------ */ + +static t_class *value_class, *vcommon_class; + +typedef struct vcommon +{ + t_pd c_pd; + int c_refcount; + t_float c_f; +} t_vcommon; + +typedef struct _value +{ + t_object x_obj; + t_symbol *x_sym; + t_float *x_floatstar; +} t_value; + + /* get a pointer to a named floating-point variable. The variable + belongs to a "vcommon" object, which is created if necessary. */ +t_float *value_get(t_symbol *s) +{ + t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class); + if (!c) + { + c = (t_vcommon *)pd_new(vcommon_class); + c->c_f = 0; + c->c_refcount = 0; + pd_bind(&c->c_pd, s); + } + c->c_refcount++; + return (&c->c_f); +} + + /* release a variable. This only frees the "vcommon" resource when the + last interested party releases it. */ +void value_release(t_symbol *s) +{ + t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class); + if (c) + { + if (!--c->c_refcount) + { + pd_unbind(&c->c_pd, s); + pd_free(&c->c_pd); + } + } + else bug("value_release"); +} + +/* + * value_getfloat -- obtain the float value of a "value" object + * return 0 on success, 1 otherwise + */ +int value_getfloat(t_symbol *s, t_float *f) +{ + t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class); + if (!c) + return (1); + *f = c->c_f; + return (0); +} + +/* + * value_setfloat -- set the float value of a "value" object + * return 0 on success, 1 otherwise + */ +int value_setfloat(t_symbol *s, t_float f) +{ + t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class); + if (!c) + return (1); + c->c_f = f; + return (0); +} + +static void vcommon_float(t_vcommon *x, t_float f) +{ + x->c_f = f; +} + +static void *value_new(t_symbol *s) +{ + t_value *x = (t_value *)pd_new(value_class); + if (!*s->s_name) + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("symbol"), gensym("symbol2")); + x->x_sym = s; + x->x_floatstar = value_get(s); + outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void value_bang(t_value *x) +{ + outlet_float(x->x_obj.ob_outlet, *x->x_floatstar); +} + +static void value_float(t_value *x, t_float f) +{ + *x->x_floatstar = f; +} + +/* set method */ +static void value_symbol2(t_value *x, t_symbol *s) +{ + value_release(x->x_sym); + x->x_sym = s; + x->x_floatstar = value_get(s); +} + +static void value_ff(t_value *x) +{ + value_release(x->x_sym); +} + +static void value_setup(void) +{ + value_class = class_new(gensym("value"), (t_newmethod)value_new, + (t_method)value_ff, + sizeof(t_value), 0, A_DEFSYM, 0); + class_addcreator((t_newmethod)value_new, gensym("v"), A_DEFSYM, 0); + class_addbang(value_class, value_bang); + class_addfloat(value_class, value_float); + class_addmethod(value_class, (t_method)value_symbol2, gensym("symbol2"), + A_DEFSYM, 0); + vcommon_class = class_new(gensym("value"), 0, 0, + sizeof(t_vcommon), CLASS_PD, 0); + class_addfloat(vcommon_class, vcommon_float); +} + +/* -------------- overall setup routine for this file ----------------- */ + +void x_connective_setup(void) +{ + pdint_setup(); + pdfloat_setup(); + pdsymbol_setup(); + bang_setup(); + send_setup(); + receive_setup(); + select_setup(); + route_setup(); + pack_setup(); + unpack_setup(); + trigger_setup(); + spigot_setup(); + moses_setup(); + until_setup(); + makefilename_setup(); + swap_setup(); + change_setup(); + value_setup(); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/x_gui.c b/ports/camomile/source/LibPd/pure-data/src/x_gui.c new file mode 100644 index 00000000..47630ff8 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_gui.c @@ -0,0 +1,397 @@ +/* Copyright (c) 1997-2000 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* dialogs. LATER, deal with the situation where the object goes +away before the panel does... */ + +#include "m_pd.h" +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +/* --------------------- graphics responder ---------------- */ + +/* make one of these if you want to put up a dialog window but want to be +protected from getting deleted and then having the dialog call you back. In +this design the calling object doesn't have to keep the address of the dialog +window around; instead we keep a list of all open dialogs. Any object that +might have dialogs, when it is deleted, simply checks down the dialog window +list and breaks off any dialogs that might later have sent messages to it. +Only when the dialog window itself closes do we delete the gfxstub object. */ + +static t_class *gfxstub_class; + +typedef struct _gfxstub +{ + t_pd x_pd; + t_pd *x_owner; + void *x_key; + t_symbol *x_sym; + struct _gfxstub *x_next; +} t_gfxstub; + +static t_gfxstub *gfxstub_list; + + /* create a new one. the "key" is an address by which the owner + will identify it later; if the owner only wants one dialog, this + could just be a pointer to the owner itself. The string "cmd" + is a TK command to create the dialog, with "%s" embedded in + it so we can provide a name by which the GUI can send us back + messages; e.g., "pdtk_canvas_dofont %s 10". */ + +void gfxstub_new(t_pd *owner, void *key, const char *cmd) +{ + char buf[4*MAXPDSTRING]; + char namebuf[80]; + char sprintfbuf[MAXPDSTRING]; + char *afterpercent; + t_int afterpercentlen; + t_gfxstub *x; + t_symbol *s; + /* if any exists with matching key, burn it. */ + for (x = gfxstub_list; x; x = x->x_next) + if (x->x_key == key) + gfxstub_deleteforkey(key); + if (strlen(cmd) + 50 > 4*MAXPDSTRING) + { + bug("audio dialog too long"); + bug("%s", cmd); + return; + } + x = (t_gfxstub *)pd_new(gfxstub_class); + sprintf(namebuf, ".gfxstub%lx", (t_int)x); + + s = gensym(namebuf); + pd_bind(&x->x_pd, s); + x->x_owner = owner; + x->x_sym = s; + x->x_key = key; + x->x_next = gfxstub_list; + gfxstub_list = x; + /* only replace first %s so sprintf() doesn't crash */ + afterpercent = strchr(cmd, '%') + 2; + afterpercentlen = afterpercent - cmd; + strncpy(sprintfbuf, cmd, afterpercentlen); + sprintfbuf[afterpercentlen] = '\0'; + sprintf(buf, sprintfbuf, s->s_name); + strncat(buf, afterpercent, (4*MAXPDSTRING) - afterpercentlen); + sys_gui(buf); +} + +static void gfxstub_offlist(t_gfxstub *x) +{ + t_gfxstub *y1, *y2; + if (gfxstub_list == x) + gfxstub_list = x->x_next; + else for (y1 = gfxstub_list; (y2 = y1->x_next); y1 = y2) + if (y2 == x) + { + y1->x_next = y2->x_next; + break; + } +} + + /* if the owner disappears, we still may have to stay around until our + dialog window signs off. Anyway we can now tell the GUI to destroy the + window. */ +void gfxstub_deleteforkey(void *key) +{ + t_gfxstub *y; + int didit = 1; + while (didit) + { + didit = 0; + for (y = gfxstub_list; y; y = y->x_next) + { + if (y->x_key == key) + { + sys_vgui("destroy .gfxstub%lx\n", y); + y->x_owner = 0; + gfxstub_offlist(y); + didit = 1; + break; + } + } + } +} + +/* --------- pd messages for gfxstub (these come from the GUI) ---------- */ + + /* "cancel" to request that we close the dialog window. */ +static void gfxstub_cancel(t_gfxstub *x) +{ + gfxstub_deleteforkey(x->x_key); +} + + /* "signoff" comes from the GUI to say the dialog window closed. */ +static void gfxstub_signoff(t_gfxstub *x) +{ + gfxstub_offlist(x); + pd_free(&x->x_pd); +} + +static t_binbuf *gfxstub_binbuf; + + /* a series of "data" messages rebuilds a scalar */ +static void gfxstub_data(t_gfxstub *x, t_symbol *s, int argc, t_atom *argv) +{ + if (!gfxstub_binbuf) + gfxstub_binbuf = binbuf_new(); + binbuf_add(gfxstub_binbuf, argc, argv); + binbuf_addsemi(gfxstub_binbuf); +} + /* the "end" message terminates rebuilding the scalar */ +static void gfxstub_end(t_gfxstub *x) +{ + canvas_dataproperties((t_canvas *)x->x_owner, + (t_scalar *)x->x_key, gfxstub_binbuf); + binbuf_free(gfxstub_binbuf); + gfxstub_binbuf = 0; +} + + /* anything else is a message from the dialog window to the owner; + just forward it. */ +static void gfxstub_anything(t_gfxstub *x, t_symbol *s, int argc, t_atom *argv) +{ + if (x->x_owner) + pd_typedmess(x->x_owner, s, argc, argv); +} + +static void gfxstub_free(t_gfxstub *x) +{ + pd_unbind(&x->x_pd, x->x_sym); +} + +static void gfxstub_setup(void) +{ + gfxstub_class = class_new(gensym("gfxstub"), 0, (t_method)gfxstub_free, + sizeof(t_gfxstub), CLASS_PD, 0); + class_addanything(gfxstub_class, gfxstub_anything); + class_addmethod(gfxstub_class, (t_method)gfxstub_signoff, + gensym("signoff"), 0); + class_addmethod(gfxstub_class, (t_method)gfxstub_data, + gensym("data"), A_GIMME, 0); + class_addmethod(gfxstub_class, (t_method)gfxstub_end, + gensym("end"), 0); + class_addmethod(gfxstub_class, (t_method)gfxstub_cancel, + gensym("cancel"), 0); +} + +/* -------------------------- openpanel ------------------------------ */ + +static t_class *openpanel_class; + +typedef struct _openpanel +{ + t_object x_obj; + t_symbol *x_s; +} t_openpanel; + +static void *openpanel_new( void) +{ + char buf[50]; + t_openpanel *x = (t_openpanel *)pd_new(openpanel_class); + sprintf(buf, "d%lx", (t_int)x); + x->x_s = gensym(buf); + pd_bind(&x->x_obj.ob_pd, x->x_s); + outlet_new(&x->x_obj, &s_symbol); + return (x); +} + +static void openpanel_symbol(t_openpanel *x, t_symbol *s) +{ + char *path = (s && s->s_name) ? s->s_name : "\"\""; + sys_vgui("pdtk_openpanel {%s} {%s}\n", x->x_s->s_name, path); +} + +static void openpanel_bang(t_openpanel *x) +{ + openpanel_symbol(x, &s_); +} + +static void openpanel_callback(t_openpanel *x, t_symbol *s) +{ + outlet_symbol(x->x_obj.ob_outlet, s); +} + + +static void openpanel_free(t_openpanel *x) +{ + pd_unbind(&x->x_obj.ob_pd, x->x_s); +} + +static void openpanel_setup(void) +{ + openpanel_class = class_new(gensym("openpanel"), + (t_newmethod)openpanel_new, (t_method)openpanel_free, + sizeof(t_openpanel), 0, 0); + class_addbang(openpanel_class, openpanel_bang); + class_addsymbol(openpanel_class, openpanel_symbol); + class_addmethod(openpanel_class, (t_method)openpanel_callback, + gensym("callback"), A_SYMBOL, 0); +} + +/* -------------------------- savepanel ------------------------------ */ + +static t_class *savepanel_class; + +typedef struct _savepanel +{ + t_object x_obj; + t_canvas *x_canvas; + t_symbol *x_s; +} t_savepanel; + +static void *savepanel_new( void) +{ + char buf[50]; + t_savepanel *x = (t_savepanel *)pd_new(savepanel_class); + sprintf(buf, "d%lx", (t_int)x); + x->x_s = gensym(buf); + x->x_canvas = canvas_getcurrent(); + pd_bind(&x->x_obj.ob_pd, x->x_s); + outlet_new(&x->x_obj, &s_symbol); + return (x); +} + +static void savepanel_symbol(t_savepanel *x, t_symbol *s) +{ + char *path = (s && s->s_name) ? s->s_name : "\"\""; + sys_vgui("pdtk_savepanel {%s} {%s}\n", x->x_s->s_name, path); +} + +static void savepanel_bang(t_savepanel *x) +{ + savepanel_symbol(x, &s_); +} + +static void savepanel_callback(t_savepanel *x, t_symbol *s) +{ + outlet_symbol(x->x_obj.ob_outlet, s); +} + +static void savepanel_free(t_savepanel *x) +{ + pd_unbind(&x->x_obj.ob_pd, x->x_s); +} + +static void savepanel_setup(void) +{ + savepanel_class = class_new(gensym("savepanel"), + (t_newmethod)savepanel_new, (t_method)savepanel_free, + sizeof(t_savepanel), 0, 0); + class_addbang(savepanel_class, savepanel_bang); + class_addsymbol(savepanel_class, savepanel_symbol); + class_addmethod(savepanel_class, (t_method)savepanel_callback, + gensym("callback"), A_SYMBOL, 0); +} + +/* ---------------------- key and its relatives ------------------ */ + +static t_class *key_class, *keyup_class, *keyname_class; + +typedef struct _key +{ + t_object x_obj; +} t_key; + +static void *key_new( void) +{ + t_key *x = (t_key *)pd_new(key_class); + outlet_new(&x->x_obj, &s_float); + pd_bind(&x->x_obj.ob_pd, gensym("#key")); + return (x); +} + +static void key_float(t_key *x, t_floatarg f) +{ + outlet_float(x->x_obj.ob_outlet, f); +} + +static void key_free(t_key *x) +{ + pd_unbind(&x->x_obj.ob_pd, gensym("#key")); +} + +typedef struct _keyup +{ + t_object x_obj; +} t_keyup; + +static void *keyup_new( void) +{ + t_keyup *x = (t_keyup *)pd_new(keyup_class); + outlet_new(&x->x_obj, &s_float); + pd_bind(&x->x_obj.ob_pd, gensym("#keyup")); + return (x); +} + +static void keyup_float(t_keyup *x, t_floatarg f) +{ + outlet_float(x->x_obj.ob_outlet, f); +} + +static void keyup_free(t_keyup *x) +{ + pd_unbind(&x->x_obj.ob_pd, gensym("#keyup")); +} + +typedef struct _keyname +{ + t_object x_obj; + t_outlet *x_outlet1; + t_outlet *x_outlet2; +} t_keyname; + +static void *keyname_new( void) +{ + t_keyname *x = (t_keyname *)pd_new(keyname_class); + x->x_outlet1 = outlet_new(&x->x_obj, &s_float); + x->x_outlet2 = outlet_new(&x->x_obj, &s_symbol); + pd_bind(&x->x_obj.ob_pd, gensym("#keyname")); + return (x); +} + +static void keyname_list(t_keyname *x, t_symbol *s, int ac, t_atom *av) +{ + outlet_symbol(x->x_outlet2, atom_getsymbolarg(1, ac, av)); + outlet_float(x->x_outlet1, atom_getfloatarg(0, ac, av)); +} + +static void keyname_free(t_keyname *x) +{ + pd_unbind(&x->x_obj.ob_pd, gensym("#keyname")); +} + +static void key_setup(void) +{ + key_class = class_new(gensym("key"), + (t_newmethod)key_new, (t_method)key_free, + sizeof(t_key), CLASS_NOINLET, 0); + class_addfloat(key_class, key_float); + + keyup_class = class_new(gensym("keyup"), + (t_newmethod)keyup_new, (t_method)keyup_free, + sizeof(t_keyup), CLASS_NOINLET, 0); + class_addfloat(keyup_class, keyup_float); + class_sethelpsymbol(keyup_class, gensym("key")); + + keyname_class = class_new(gensym("keyname"), + (t_newmethod)keyname_new, (t_method)keyname_free, + sizeof(t_keyname), CLASS_NOINLET, 0); + class_addlist(keyname_class, keyname_list); + class_sethelpsymbol(keyname_class, gensym("key")); +} + +/* -------------------------- setup routine ------------------------------ */ + +void x_gui_setup(void) +{ + gfxstub_setup(); + openpanel_setup(); + savepanel_setup(); + key_setup(); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/x_interface.c b/ports/camomile/source/LibPd/pure-data/src/x_interface.c new file mode 100644 index 00000000..ce685e57 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_interface.c @@ -0,0 +1,97 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* interface objects */ + +#include "m_pd.h" +#include + +/* -------------------------- print ------------------------------ */ +static t_class *print_class; + +typedef struct _print +{ + t_object x_obj; + t_symbol *x_sym; +} t_print; + +static void *print_new(t_symbol *sel, int argc, t_atom *argv) +{ + t_print *x = (t_print *)pd_new(print_class); + if (argc == 0) + x->x_sym = gensym("print"); + else if (argc == 1 && argv->a_type == A_SYMBOL) + { + t_symbol *s = atom_getsymbolarg(0, argc, argv); + if (!strcmp(s->s_name, "-n")) + x->x_sym = &s_; + else x->x_sym = s; + } + else + { + int bufsize; + char *buf; + t_binbuf *bb = binbuf_new(); + binbuf_add(bb, argc, argv); + binbuf_gettext(bb, &buf, &bufsize); + buf = resizebytes(buf, bufsize, bufsize+1); + buf[bufsize] = 0; + x->x_sym = gensym(buf); + freebytes(buf, bufsize+1); + binbuf_free(bb); + } + return (x); +} + +static void print_bang(t_print *x) +{ + post("%s%sbang", x->x_sym->s_name, (*x->x_sym->s_name ? ": " : "")); +} + +static void print_pointer(t_print *x, t_gpointer *gp) +{ + post("%s%s(gpointer)", x->x_sym->s_name, (*x->x_sym->s_name ? ": " : "")); +} + +static void print_float(t_print *x, t_float f) +{ + post("%s%s%g", x->x_sym->s_name, (*x->x_sym->s_name ? ": " : ""), f); +} + +static void print_list(t_print *x, t_symbol *s, int argc, t_atom *argv) +{ + int i; + if (argc && argv->a_type != A_SYMBOL) startpost("%s:", x->x_sym->s_name); + else startpost("%s%s%s", x->x_sym->s_name, + (*x->x_sym->s_name ? ": " : ""), + (argc > 1 ? s_list.s_name : (argc == 1 ? s_symbol.s_name : + s_bang.s_name))); + postatom(argc, argv); + endpost(); +} + +static void print_anything(t_print *x, t_symbol *s, int argc, t_atom *argv) +{ + int i; + startpost("%s%s%s", x->x_sym->s_name, (*x->x_sym->s_name ? ": " : ""), + s->s_name); + postatom(argc, argv); + endpost(); +} + +static void print_setup(void) +{ + print_class = class_new(gensym("print"), (t_newmethod)print_new, 0, + sizeof(t_print), 0, A_GIMME, 0); + class_addbang(print_class, print_bang); + class_addfloat(print_class, print_float); + class_addpointer(print_class, print_pointer); + class_addlist(print_class, print_list); + class_addanything(print_class, print_anything); +} + +void x_interface_setup(void) +{ + print_setup(); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/x_list.c b/ports/camomile/source/LibPd/pure-data/src/x_list.c new file mode 100644 index 00000000..746db06e --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_list.c @@ -0,0 +1,807 @@ +/* Copyright (c) 1997- Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include + +#ifdef _WIN32 +# include /* MSVC or mingw on windows */ +#elif defined(__linux__) || defined(__APPLE__) +# include /* linux, mac, mingw, cygwin */ +#else +# include /* BSDs for example */ +#endif + +#ifndef HAVE_ALLOCA /* can work without alloca() but we never need it */ +#define HAVE_ALLOCA 1 +#endif + +#define LIST_NGETBYTE 100 /* bigger that this we use alloc, not alloca */ + +/* the "list" object family. + + list append - append a list to another + list prepend - prepend a list to another + list split - first n elements to first outlet, rest to second outlet + list trim - trim off "list" selector + list length - output number of items in list + list fromsymbol - "explode" a symbol into a list of character codes + +Need to think more about: + list foreach - spit out elements of a list one by one (also in reverse?) + list reverse - permute elements of a list back to front + list cat - build a list by accumulating elements + +Probably don't need: + list first - output first n elements. + list last - output last n elements + list nth - nth item in list, counting from zero + list array - get items from a named array as a list + list pack - synonym for 'pack' + list unpack - synonym for 'unpack' +*/ + +/* -------------- utility functions: storage, copying -------------- */ + /* List element for storage. Keep an atom and, in case it's a pointer, + an associated 'gpointer' to protect against stale pointers. */ +typedef struct _listelem +{ + t_atom l_a; + t_gpointer l_p; +} t_listelem; + +typedef struct _alist +{ + t_pd l_pd; /* object to point inlets to */ + int l_n; /* number of items */ + int l_npointer; /* number of pointers */ + t_listelem *l_vec; /* pointer to items */ +} t_alist; + +#if HAVE_ALLOCA +#define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)((n) < LIST_NGETBYTE ? \ + alloca((n) * sizeof(t_atom)) : getbytes((n) * sizeof(t_atom)))) +#define ATOMS_FREEA(x, n) ( \ + ((n) < LIST_NGETBYTE || (freebytes((x), (n) * sizeof(t_atom)), 0))) +#else +#define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)getbytes((n) * sizeof(t_atom))) +#define ATOMS_FREEA(x, n) (freebytes((x), (n) * sizeof(t_atom))) +#endif + +static void atoms_copy(int argc, t_atom *from, t_atom *to) +{ + int i; + for (i = 0; i < argc; i++) + to[i] = from[i]; +} + +/* ------------- fake class to divert inlets to ----------------- */ + +t_class *alist_class; + +static void alist_init(t_alist *x) +{ + x->l_pd = alist_class; + x->l_n = x->l_npointer = 0; + x->l_vec = 0; +} + +static void alist_clear(t_alist *x) +{ + int i; + for (i = 0; i < x->l_n; i++) + { + if (x->l_vec[i].l_a.a_type == A_POINTER) + gpointer_unset(x->l_vec[i].l_a.a_w.w_gpointer); + } + if (x->l_vec) + freebytes(x->l_vec, x->l_n * sizeof(*x->l_vec)); +} + +static void alist_copyin(t_alist *x, t_symbol *s, int argc, t_atom *argv, + int where) +{ + int i, j; + for (i = 0, j = where; i < argc; i++, j++) + { + x->l_vec[j].l_a = argv[i]; + if (x->l_vec[j].l_a.a_type == A_POINTER) + { + x->l_npointer++; + gpointer_copy(x->l_vec[j].l_a.a_w.w_gpointer, &x->l_vec[j].l_p); + x->l_vec[j].l_a.a_w.w_gpointer = &x->l_vec[j].l_p; + } + } +} + + /* set contents to a list */ +static void alist_list(t_alist *x, t_symbol *s, int argc, t_atom *argv) +{ + alist_clear(x); + if (!(x->l_vec = (t_listelem *)getbytes(argc * sizeof(*x->l_vec)))) + { + x->l_n = 0; + error("list: out of memory"); + return; + } + x->l_n = argc; + x->l_npointer = 0; + alist_copyin(x, s, argc, argv, 0); +} + + /* set contents to an arbitrary non-list message */ +static void alist_anything(t_alist *x, t_symbol *s, int argc, t_atom *argv) +{ + int i; + alist_clear(x); + if (!(x->l_vec = (t_listelem *)getbytes((argc+1) * sizeof(*x->l_vec)))) + { + x->l_n = 0; + error("list_alloc: out of memory"); + return; + } + x->l_n = argc+1; + x->l_npointer = 0; + SETSYMBOL(&x->l_vec[0].l_a, s); + for (i = 0; i < argc; i++) + { + x->l_vec[i+1].l_a = argv[i]; + if (x->l_vec[i+1].l_a.a_type == A_POINTER) + { + x->l_npointer++; + gpointer_copy(x->l_vec[i+1].l_a.a_w.w_gpointer, &x->l_vec[i+1].l_p); + x->l_vec[i+1].l_a.a_w.w_gpointer = &x->l_vec[i+1].l_p; + } + } +} + +static void alist_toatoms(t_alist *x, t_atom *to, int onset, int count) +{ + int i; + for (i = 0; i < count; i++) + to[i] = x->l_vec[onset + i].l_a; +} + + +static void alist_clone(t_alist *x, t_alist *y, int onset, int count) +{ + int i; + y->l_pd = alist_class; + y->l_n = count; + y->l_npointer = 0; + if (!(y->l_vec = (t_listelem *)getbytes(y->l_n * sizeof(*y->l_vec)))) + { + y->l_n = 0; + error("list_alloc: out of memory"); + } + else for (i = 0; i < count; i++) + { + y->l_vec[i].l_a = x->l_vec[onset + i].l_a; + if (y->l_vec[i].l_a.a_type == A_POINTER) + { + gpointer_copy(y->l_vec[i].l_a.a_w.w_gpointer, &y->l_vec[i].l_p); + y->l_vec[i].l_a.a_w.w_gpointer = &y->l_vec[i].l_p; + y->l_npointer++; + } + } +} + +static void alist_setup(void) +{ + alist_class = class_new(gensym("list inlet"), + 0, 0, sizeof(t_alist), 0, 0); + class_addlist(alist_class, alist_list); + class_addanything(alist_class, alist_anything); +} + +/* ------------- list append --------------------- */ + +t_class *list_append_class; + +typedef struct _list_append +{ + t_object x_obj; + t_alist x_alist; +} t_list_append; + +static void *list_append_new(t_symbol *s, int argc, t_atom *argv) +{ + t_list_append *x = (t_list_append *)pd_new(list_append_class); + alist_init(&x->x_alist); + alist_list(&x->x_alist, 0, argc, argv); + outlet_new(&x->x_obj, &s_list); + inlet_new(&x->x_obj, &x->x_alist.l_pd, 0, 0); + return (x); +} + +static void list_append_list(t_list_append *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_atom *outv; + int n, outc = x->x_alist.l_n + argc; + ATOMS_ALLOCA(outv, outc); + atoms_copy(argc, argv, outv); + if (x->x_alist.l_npointer) + { + t_alist y; + alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n); + alist_toatoms(&y, outv+argc, 0, x->x_alist.l_n); + outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); + alist_clear(&y); + } + else + { + alist_toatoms(&x->x_alist, outv+argc, 0, x->x_alist.l_n); + outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); + } + ATOMS_FREEA(outv, outc); +} + +static void list_append_anything(t_list_append *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_atom *outv; + int n, outc = x->x_alist.l_n + argc + 1; + ATOMS_ALLOCA(outv, outc); + SETSYMBOL(outv, s); + atoms_copy(argc, argv, outv + 1); + if (x->x_alist.l_npointer) + { + t_alist y; + alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n); + alist_toatoms(&y, outv + 1 + argc, 0, x->x_alist.l_n); + outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); + alist_clear(&y); + } + else + { + alist_toatoms(&x->x_alist, outv + 1 + argc, 0, x->x_alist.l_n); + outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); + } + ATOMS_FREEA(outv, outc); +} + +static void list_append_append(t_list_append *x, t_symbol *s, + int argc, t_atom *argv) +{ + if (!(x->x_alist.l_vec = (t_listelem *)resizebytes(x->x_alist.l_vec, + (x->x_alist.l_n) * sizeof(*x->x_alist.l_vec), + (x->x_alist.l_n + argc) * sizeof(*x->x_alist.l_vec)))) + { + x->x_alist.l_n = 0; + error("list: out of memory"); + return; + } + alist_copyin(&x->x_alist, s, argc, argv, x->x_alist.l_n); + x->x_alist.l_n += argc; +} + +static void list_append_prepend(t_list_append *x, t_symbol *s, + int argc, t_atom *argv) +{ + if (!(x->x_alist.l_vec = (t_listelem *)resizebytes(x->x_alist.l_vec, + (x->x_alist.l_n) * sizeof(*x->x_alist.l_vec), + (x->x_alist.l_n + argc) * sizeof(*x->x_alist.l_vec)))) + { + x->x_alist.l_n = 0; + error("list: out of memory"); + return; + } + memmove(x->x_alist.l_vec + argc, x->x_alist.l_vec, + x->x_alist.l_n * sizeof(*x->x_alist.l_vec)); + alist_copyin(&x->x_alist, s, argc, argv, 0); + x->x_alist.l_n += argc; +} + +static void list_append_free(t_list_append *x) +{ + alist_clear(&x->x_alist); +} + +static void list_append_setup(void) +{ + list_append_class = class_new(gensym("list append"), + (t_newmethod)list_append_new, (t_method)list_append_free, + sizeof(t_list_append), 0, A_GIMME, 0); + class_addlist(list_append_class, list_append_list); + class_addanything(list_append_class, list_append_anything); + class_sethelpsymbol(list_append_class, &s_list); +} + +/* ------------- list prepend --------------------- */ + +t_class *list_prepend_class; + +typedef t_list_append t_list_prepend; + +static void *list_prepend_new(t_symbol *s, int argc, t_atom *argv) +{ + t_list_prepend *x = (t_list_prepend *)pd_new(list_prepend_class); + alist_init(&x->x_alist); + alist_list(&x->x_alist, 0, argc, argv); + outlet_new(&x->x_obj, &s_list); + inlet_new(&x->x_obj, &x->x_alist.l_pd, 0, 0); + return (x); +} + +static void list_prepend_list(t_list_prepend *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_atom *outv; + int n, outc = x->x_alist.l_n + argc; + ATOMS_ALLOCA(outv, outc); + atoms_copy(argc, argv, outv + x->x_alist.l_n); + if (x->x_alist.l_npointer) + { + t_alist y; + alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n); + alist_toatoms(&y, outv, 0, x->x_alist.l_n); + outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); + alist_clear(&y); + } + else + { + alist_toatoms(&x->x_alist, outv, 0, x->x_alist.l_n); + outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); + } + ATOMS_FREEA(outv, outc); +} + +static void list_prepend_anything(t_list_prepend *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_atom *outv; + int n, outc = x->x_alist.l_n + argc + 1; + ATOMS_ALLOCA(outv, outc); + SETSYMBOL(outv + x->x_alist.l_n, s); + atoms_copy(argc, argv, outv + x->x_alist.l_n + 1); + if (x->x_alist.l_npointer) + { + t_alist y; + alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n); + alist_toatoms(&y, outv, 0, x->x_alist.l_n); + outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); + alist_clear(&y); + } + else + { + alist_toatoms(&x->x_alist, outv, 0, x->x_alist.l_n); + outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); + } + ATOMS_FREEA(outv, outc); +} + +static void list_prepend_free(t_list_prepend *x) +{ + alist_clear(&x->x_alist); +} + +static void list_prepend_setup(void) +{ + list_prepend_class = class_new(gensym("list prepend"), + (t_newmethod)list_prepend_new, (t_method)list_prepend_free, + sizeof(t_list_prepend), 0, A_GIMME, 0); + class_addlist(list_prepend_class, list_prepend_list); + class_addanything(list_prepend_class, list_prepend_anything); + class_sethelpsymbol(list_prepend_class, &s_list); +} + +/* ------------- list store --------------------- */ + +t_class *list_store_class; + +typedef struct _list_store +{ + t_object x_obj; + t_alist x_alist; + t_outlet *x_out1; + t_outlet *x_out2; +} t_list_store; + +static void *list_store_new(t_symbol *s, int argc, t_atom *argv) +{ + t_list_store *x = (t_list_store *)pd_new(list_store_class); + alist_init(&x->x_alist); + alist_list(&x->x_alist, 0, argc, argv); + x->x_out1 = outlet_new(&x->x_obj, &s_list); + x->x_out2 = outlet_new(&x->x_obj, &s_bang); + inlet_new(&x->x_obj, &x->x_alist.l_pd, 0, 0); + return (x); +} + +static void list_store_list(t_list_store *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_atom *outv; + int n, outc = x->x_alist.l_n + argc; + ATOMS_ALLOCA(outv, outc); + atoms_copy(argc, argv, outv); + if (x->x_alist.l_npointer) + { + t_alist y; + alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n); + alist_toatoms(&y, outv+argc, 0, x->x_alist.l_n); + outlet_list(x->x_out1, &s_list, outc, outv); + alist_clear(&y); + } + else + { + alist_toatoms(&x->x_alist, outv+argc, 0, x->x_alist.l_n); + outlet_list(x->x_out1, &s_list, outc, outv); + } + ATOMS_FREEA(outv, outc); +} + +/* function to restore gpointers after the list has moved in memory */ +static void list_store_restore_gpointers(t_list_store *x, int offset, int count) +{ + t_listelem *vec = x->x_alist.l_vec + offset; + while (count--) + { + if (vec->l_a.a_type == A_POINTER) + vec->l_a.a_w.w_gpointer = &vec->l_p; + vec++; + } +} + +static void list_store_append(t_list_store *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_listelem *oldptr = x->x_alist.l_vec; + + if (!(x->x_alist.l_vec = (t_listelem *)resizebytes(x->x_alist.l_vec, + (x->x_alist.l_n) * sizeof(*x->x_alist.l_vec), + (x->x_alist.l_n + argc) * sizeof(*x->x_alist.l_vec)))) + { + x->x_alist.l_n = 0; + error("list: out of memory"); + return; + } + + /* fix gpointers if resizebytes() has moved the alist in memory */ + if (x->x_alist.l_vec != oldptr && x->x_alist.l_npointer) + list_store_restore_gpointers(x, 0, x->x_alist.l_n); + + alist_copyin(&x->x_alist, s, argc, argv, x->x_alist.l_n); + x->x_alist.l_n += argc; +} + +static void list_store_prepend(t_list_store *x, t_symbol *s, + int argc, t_atom *argv) +{ + if (!(x->x_alist.l_vec = (t_listelem *)resizebytes(x->x_alist.l_vec, + (x->x_alist.l_n) * sizeof(*x->x_alist.l_vec), + (x->x_alist.l_n + argc) * sizeof(*x->x_alist.l_vec)))) + { + x->x_alist.l_n = 0; + error("list: out of memory"); + return; + } + + memmove(x->x_alist.l_vec + argc, x->x_alist.l_vec, + x->x_alist.l_n * sizeof(*x->x_alist.l_vec)); + + /* we always have to fix gpointers because of memmove() */ + if (x->x_alist.l_npointer) + list_store_restore_gpointers(x, argc, x->x_alist.l_n); + + alist_copyin(&x->x_alist, s, argc, argv, 0); + x->x_alist.l_n += argc; +} + +static void list_store_get(t_list_store *x, float f1, float f2) +{ + t_atom *outv; + int onset = f1, outc = f2; + if (onset < 0 || outc < 0) + { + pd_error(x, "list_store_get: negative range (%d %d)", onset, outc); + return; + } + if (onset + outc > x->x_alist.l_n) + { + outlet_bang(x->x_out2); + return; + } + ATOMS_ALLOCA(outv, outc); + if (x->x_alist.l_npointer) + { + t_alist y; + alist_clone(&x->x_alist, &y, onset, outc); + alist_toatoms(&y, outv, 0, outc); + outlet_list(x->x_out1, &s_list, outc, outv); + alist_clear(&y); + } + else + { + alist_toatoms(&x->x_alist, outv, onset, outc); + outlet_list(x->x_out1, &s_list, outc, outv); + } + ATOMS_FREEA(outv, outc); +} + +static void list_store_free(t_list_store *x) +{ + alist_clear(&x->x_alist); +} + +static void list_store_setup(void) +{ + list_store_class = class_new(gensym("list store"), + (t_newmethod)list_store_new, (t_method)list_store_free, + sizeof(t_list_store), 0, A_GIMME, 0); + class_addlist(list_store_class, list_store_list); + class_addmethod(list_store_class, (t_method)list_store_append, + gensym("append"), A_GIMME, 0); + class_addmethod(list_store_class, (t_method)list_store_prepend, + gensym("prepend"), A_GIMME, 0); + class_addmethod(list_store_class, (t_method)list_store_get, + gensym("get"), A_FLOAT, A_FLOAT, 0); + class_sethelpsymbol(list_store_class, &s_list); +} + +/* ------------- list split --------------------- */ + +t_class *list_split_class; + +typedef struct _list_split +{ + t_object x_obj; + t_float x_f; + t_outlet *x_out1; + t_outlet *x_out2; + t_outlet *x_out3; +} t_list_split; + +static void *list_split_new(t_floatarg f) +{ + t_list_split *x = (t_list_split *)pd_new(list_split_class); + x->x_out1 = outlet_new(&x->x_obj, &s_list); + x->x_out2 = outlet_new(&x->x_obj, &s_list); + x->x_out3 = outlet_new(&x->x_obj, &s_list); + floatinlet_new(&x->x_obj, &x->x_f); + x->x_f = f; + return (x); +} + +static void list_split_list(t_list_split *x, t_symbol *s, + int argc, t_atom *argv) +{ + int n = x->x_f; + if (n < 0) + n = 0; + if (argc >= n) + { + outlet_list(x->x_out2, &s_list, argc-n, argv+n); + outlet_list(x->x_out1, &s_list, n, argv); + } + else outlet_list(x->x_out3, &s_list, argc, argv); +} + +static void list_split_anything(t_list_split *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_atom *outv; + ATOMS_ALLOCA(outv, argc+1); + SETSYMBOL(outv, s); + atoms_copy(argc, argv, outv + 1); + list_split_list(x, &s_list, argc+1, outv); + ATOMS_FREEA(outv, argc+1); +} + +static void list_split_setup(void) +{ + list_split_class = class_new(gensym("list split"), + (t_newmethod)list_split_new, 0, + sizeof(t_list_split), 0, A_DEFFLOAT, 0); + class_addlist(list_split_class, list_split_list); + class_addanything(list_split_class, list_split_anything); + class_sethelpsymbol(list_split_class, &s_list); +} + +/* ------------- list trim --------------------- */ + +t_class *list_trim_class; + +typedef struct _list_trim +{ + t_object x_obj; +} t_list_trim; + +static void *list_trim_new( void) +{ + t_list_trim *x = (t_list_trim *)pd_new(list_trim_class); + outlet_new(&x->x_obj, &s_list); + return (x); +} + +static void list_trim_list(t_list_trim *x, t_symbol *s, + int argc, t_atom *argv) +{ + if (argc < 1 || argv[0].a_type != A_SYMBOL) + outlet_list(x->x_obj.ob_outlet, &s_list, argc, argv); + else outlet_anything(x->x_obj.ob_outlet, argv[0].a_w.w_symbol, + argc-1, argv+1); +} + +static void list_trim_anything(t_list_trim *x, t_symbol *s, + int argc, t_atom *argv) +{ + outlet_anything(x->x_obj.ob_outlet, s, argc, argv); +} + +static void list_trim_setup(void) +{ + list_trim_class = class_new(gensym("list trim"), + (t_newmethod)list_trim_new, 0, + sizeof(t_list_trim), 0, 0); + class_addlist(list_trim_class, list_trim_list); + class_addanything(list_trim_class, list_trim_anything); + class_sethelpsymbol(list_trim_class, &s_list); +} + +/* ------------- list length --------------------- */ + +t_class *list_length_class; + +typedef struct _list_length +{ + t_object x_obj; +} t_list_length; + +static void *list_length_new( void) +{ + t_list_length *x = (t_list_length *)pd_new(list_length_class); + outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void list_length_list(t_list_length *x, t_symbol *s, + int argc, t_atom *argv) +{ + outlet_float(x->x_obj.ob_outlet, (t_float)argc); +} + +static void list_length_anything(t_list_length *x, t_symbol *s, + int argc, t_atom *argv) +{ + outlet_float(x->x_obj.ob_outlet, (t_float)argc+1); +} + +static void list_length_setup(void) +{ + list_length_class = class_new(gensym("list length"), + (t_newmethod)list_length_new, 0, + sizeof(t_list_length), 0, 0); + class_addlist(list_length_class, list_length_list); + class_addanything(list_length_class, list_length_anything); + class_sethelpsymbol(list_length_class, &s_list); +} + +/* ------------- list fromsymbol --------------------- */ + +t_class *list_fromsymbol_class; + +typedef struct _list_fromsymbol +{ + t_object x_obj; +} t_list_fromsymbol; + +static void *list_fromsymbol_new( void) +{ + t_list_fromsymbol *x = (t_list_fromsymbol *)pd_new(list_fromsymbol_class); + outlet_new(&x->x_obj, &s_list); + return (x); +} + +static void list_fromsymbol_symbol(t_list_fromsymbol *x, t_symbol *s) +{ + t_atom *outv; + int n, outc = (int)strlen(s->s_name); + ATOMS_ALLOCA(outv, outc); + for (n = 0; n < outc; n++) + SETFLOAT(outv + n, (unsigned char)s->s_name[n]); + outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); + ATOMS_FREEA(outv, outc); +} + +static void list_fromsymbol_setup(void) +{ + list_fromsymbol_class = class_new(gensym("list fromsymbol"), + (t_newmethod)list_fromsymbol_new, 0, sizeof(t_list_fromsymbol), 0, 0); + class_addsymbol(list_fromsymbol_class, list_fromsymbol_symbol); + class_sethelpsymbol(list_fromsymbol_class, &s_list); +} + +/* ------------- list tosymbol --------------------- */ + +t_class *list_tosymbol_class; + +typedef struct _list_tosymbol +{ + t_object x_obj; +} t_list_tosymbol; + +static void *list_tosymbol_new( void) +{ + t_list_tosymbol *x = (t_list_tosymbol *)pd_new(list_tosymbol_class); + outlet_new(&x->x_obj, &s_symbol); + return (x); +} + +static void list_tosymbol_list(t_list_tosymbol *x, t_symbol *s, + int argc, t_atom *argv) +{ + int i; +#if HAVE_ALLOCA + char *str = alloca(argc + 1); +#else + char *str = getbytes(argc + 1); +#endif + for (i = 0; i < argc; i++) + str[i] = (char)atom_getfloatarg(i, argc, argv); + str[argc] = 0; + outlet_symbol(x->x_obj.ob_outlet, gensym(str)); +#if HAVE_ALLOCA +#else + freebytes(str, argc+1); +#endif +} + +static void list_tosymbol_setup(void) +{ + list_tosymbol_class = class_new(gensym("list tosymbol"), + (t_newmethod)list_tosymbol_new, 0, sizeof(t_list_tosymbol), 0, 0); + class_addlist(list_tosymbol_class, list_tosymbol_list); + class_sethelpsymbol(list_tosymbol_class, &s_list); +} + +/* ------------- list ------------------- */ + +static void *list_new(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) +{ + if (!argc || argv[0].a_type != A_SYMBOL) + pd_this->pd_newest = list_append_new(s, argc, argv); + else + { + t_symbol *s2 = argv[0].a_w.w_symbol; + if (s2 == gensym("append")) + pd_this->pd_newest = list_append_new(s, argc-1, argv+1); + else if (s2 == gensym("prepend")) + pd_this->pd_newest = list_prepend_new(s, argc-1, argv+1); + else if (s2 == gensym("split")) + pd_this->pd_newest = + list_split_new(atom_getfloatarg(1, argc, argv)); + else if (s2 == gensym("trim")) + pd_this->pd_newest = list_trim_new(); + else if (s2 == gensym("length")) + pd_this->pd_newest = list_length_new(); + else if (s2 == gensym("fromsymbol")) + pd_this->pd_newest = list_fromsymbol_new(); + else if (s2 == gensym("tosymbol")) + pd_this->pd_newest = list_tosymbol_new(); + else if (s2 == gensym("store")) + pd_this->pd_newest = list_store_new(s, argc-1, argv+1); + else + { + error("list %s: unknown function", s2->s_name); + pd_this->pd_newest = 0; + } + } + return (pd_this->pd_newest); +} + +void x_list_setup(void) +{ + alist_setup(); + list_append_setup(); + list_prepend_setup(); + list_store_setup(); + list_split_setup(); + list_trim_setup(); + list_length_setup(); + list_fromsymbol_setup(); + list_tosymbol_setup(); + class_addcreator((t_newmethod)list_new, &s_list, A_GIMME, 0); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/x_midi.c b/ports/camomile/source/LibPd/pure-data/src/x_midi.c new file mode 100644 index 00000000..ffee9df8 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_midi.c @@ -0,0 +1,1247 @@ +/* Copyright (c) 1997-2001 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* MIDI. */ + +#include "m_pd.h" +void outmidi_noteon(int portno, int channel, int pitch, int velo); +void outmidi_controlchange(int portno, int channel, int ctlno, int value); +void outmidi_programchange(int portno, int channel, int value); +void outmidi_pitchbend(int portno, int channel, int value); +void outmidi_aftertouch(int portno, int channel, int value); +void outmidi_polyaftertouch(int portno, int channel, int pitch, int value); +void outmidi_byte(int portno, int value); + +struct _instancemidi +{ + t_symbol *m_midiin_sym; + t_symbol *m_sysexin_sym; + t_symbol *m_notein_sym; + t_symbol *m_ctlin_sym; + t_symbol *m_pgmin_sym; + t_symbol *m_bendin_sym; + t_symbol *m_touchin_sym; + t_symbol *m_polytouchin_sym; + t_symbol *m_midirealtimein_sym; +}; + +/* ----------------------- midiin and sysexin ------------------------- */ + +static t_class *midiin_class, *sysexin_class; + +typedef struct _midiin +{ + t_object x_obj; + t_outlet *x_outlet1; + t_outlet *x_outlet2; +} t_midiin; + +static void *midiin_new(void) +{ + t_midiin *x = (t_midiin *)pd_new(midiin_class); + x->x_outlet1 = outlet_new(&x->x_obj, &s_float); + x->x_outlet2 = outlet_new(&x->x_obj, &s_float); + pd_bind(&x->x_obj.ob_pd, pd_this->pd_midi->m_midiin_sym); + return (x); +} + +static void midiin_list(t_midiin *x, t_symbol *s, int ac, t_atom *av) +{ + outlet_float(x->x_outlet2, atom_getfloatarg(1, ac, av) + 1); + outlet_float(x->x_outlet1, atom_getfloatarg(0, ac, av)); +} + +static void midiin_free(t_midiin *x) +{ + pd_unbind(&x->x_obj.ob_pd, pd_this->pd_midi->m_midiin_sym); +} + +static void *sysexin_new(void) +{ + t_midiin *x = (t_midiin *)pd_new(sysexin_class); + x->x_outlet1 = outlet_new(&x->x_obj, &s_float); + x->x_outlet2 = outlet_new(&x->x_obj, &s_float); + pd_bind(&x->x_obj.ob_pd, pd_this->pd_midi->m_sysexin_sym); + return (x); +} + +static void sysexin_free(t_midiin *x) +{ + pd_unbind(&x->x_obj.ob_pd, pd_this->pd_midi->m_sysexin_sym); +} + +static void midiin_setup(void) +{ + midiin_class = class_new(gensym("midiin"), (t_newmethod)midiin_new, + (t_method)midiin_free, sizeof(t_midiin), + CLASS_NOINLET, A_DEFFLOAT, 0); + class_addlist(midiin_class, midiin_list); + class_sethelpsymbol(midiin_class, gensym("midi")); + + sysexin_class = class_new(gensym("sysexin"), (t_newmethod)sysexin_new, + (t_method)sysexin_free, sizeof(t_midiin), + CLASS_NOINLET, A_DEFFLOAT, 0); + class_addlist(sysexin_class, midiin_list); + class_sethelpsymbol(sysexin_class, gensym("midi")); +} + +void inmidi_byte(int portno, int byte) +{ + t_atom at[2]; + if (pd_this->pd_midi->m_midiin_sym->s_thing) + { + SETFLOAT(at, byte); + SETFLOAT(at+1, portno); + pd_list(pd_this->pd_midi->m_midiin_sym->s_thing, 0, 2, at); + } +} + +void inmidi_sysex(int portno, int byte) +{ + t_atom at[2]; + if (pd_this->pd_midi->m_sysexin_sym->s_thing) + { + SETFLOAT(at, byte); + SETFLOAT(at+1, portno); + pd_list(pd_this->pd_midi->m_sysexin_sym->s_thing, 0, 2, at); + } +} + +/* ----------------------- notein ------------------------- */ + +static t_class *notein_class; + +typedef struct _notein +{ + t_object x_obj; + t_float x_channel; + t_outlet *x_outlet1; + t_outlet *x_outlet2; + t_outlet *x_outlet3; +} t_notein; + +static void *notein_new(t_floatarg f) +{ + t_notein *x = (t_notein *)pd_new(notein_class); + x->x_channel = f; + x->x_outlet1 = outlet_new(&x->x_obj, &s_float); + x->x_outlet2 = outlet_new(&x->x_obj, &s_float); + if (f == 0) x->x_outlet3 = outlet_new(&x->x_obj, &s_float); + pd_bind(&x->x_obj.ob_pd, pd_this->pd_midi->m_notein_sym); + return (x); +} + +static void notein_list(t_notein *x, t_symbol *s, int argc, t_atom *argv) +{ + t_float pitch = atom_getfloatarg(0, argc, argv); + t_float velo = atom_getfloatarg(1, argc, argv); + t_float channel = atom_getfloatarg(2, argc, argv); + if (x->x_channel != 0) + { + if (channel != x->x_channel) return; + outlet_float(x->x_outlet2, velo); + outlet_float(x->x_outlet1, pitch); + } + else + { + outlet_float(x->x_outlet3, channel); + outlet_float(x->x_outlet2, velo); + outlet_float(x->x_outlet1, pitch); + } +} + +static void notein_free(t_notein *x) +{ + pd_unbind(&x->x_obj.ob_pd, pd_this->pd_midi->m_notein_sym); +} + +static void notein_setup(void) +{ + notein_class = class_new(gensym("notein"), (t_newmethod)notein_new, + (t_method)notein_free, sizeof(t_notein), CLASS_NOINLET, A_DEFFLOAT, 0); + class_addlist(notein_class, notein_list); + class_sethelpsymbol(notein_class, gensym("midi")); +} + +void inmidi_noteon(int portno, int channel, int pitch, int velo) +{ + if (pd_this->pd_midi->m_notein_sym->s_thing) + { + t_atom at[3]; + SETFLOAT(at, pitch); + SETFLOAT(at+1, velo); + SETFLOAT(at+2, (channel + (portno << 4) + 1)); + pd_list(pd_this->pd_midi->m_notein_sym->s_thing, &s_list, 3, at); + } +} + +/* ----------------------- ctlin ------------------------- */ + +static t_class *ctlin_class; + +typedef struct _ctlin +{ + t_object x_obj; + t_float x_channel; + t_float x_ctlno; + t_outlet *x_outlet1; + t_outlet *x_outlet2; + t_outlet *x_outlet3; +} t_ctlin; + +static void *ctlin_new(t_symbol *s, int argc, t_atom *argv) +{ + int ctlno, channel; + t_ctlin *x = (t_ctlin *)pd_new(ctlin_class); + if (!argc) ctlno = -1; + else ctlno = atom_getfloatarg(0, argc, argv); + channel = atom_getfloatarg(1, argc, argv); + x->x_channel = channel; + x->x_ctlno = ctlno; + x->x_outlet1 = outlet_new(&x->x_obj, &s_float); + if (!channel) + { + if (x->x_ctlno < 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float); + x->x_outlet3 = outlet_new(&x->x_obj, &s_float); + } + pd_bind(&x->x_obj.ob_pd, pd_this->pd_midi->m_ctlin_sym); + return (x); +} + +static void ctlin_list(t_ctlin *x, t_symbol *s, int argc, t_atom *argv) +{ + t_float ctlnumber = atom_getfloatarg(0, argc, argv); + t_float value = atom_getfloatarg(1, argc, argv); + t_float channel = atom_getfloatarg(2, argc, argv); + if (x->x_ctlno >= 0 && x->x_ctlno != ctlnumber) return; + if (x->x_channel > 0 && x->x_channel != channel) return; + if (x->x_channel == 0) outlet_float(x->x_outlet3, channel); + if (x->x_ctlno < 0) outlet_float(x->x_outlet2, ctlnumber); + outlet_float(x->x_outlet1, value); +} + +static void ctlin_free(t_ctlin *x) +{ + pd_unbind(&x->x_obj.ob_pd, pd_this->pd_midi->m_ctlin_sym); +} + +static void ctlin_setup(void) +{ + ctlin_class = class_new(gensym("ctlin"), (t_newmethod)ctlin_new, + (t_method)ctlin_free, sizeof(t_ctlin), + CLASS_NOINLET, A_GIMME, 0); + class_addlist(ctlin_class, ctlin_list); + class_sethelpsymbol(ctlin_class, gensym("midi")); +} + +void inmidi_controlchange(int portno, int channel, int ctlnumber, int value) +{ + if (pd_this->pd_midi->m_ctlin_sym->s_thing) + { + t_atom at[3]; + SETFLOAT(at, ctlnumber); + SETFLOAT(at+1, value); + SETFLOAT(at+2, (channel + (portno << 4) + 1)); + pd_list(pd_this->pd_midi->m_ctlin_sym->s_thing, &s_list, 3, at); + } +} + +/* ----------------------- pgmin ------------------------- */ + +static t_class *pgmin_class; + +typedef struct _pgmin +{ + t_object x_obj; + t_float x_channel; + t_outlet *x_outlet1; + t_outlet *x_outlet2; +} t_pgmin; + +static void *pgmin_new(t_floatarg f) +{ + t_pgmin *x = (t_pgmin *)pd_new(pgmin_class); + x->x_channel = f; + x->x_outlet1 = outlet_new(&x->x_obj, &s_float); + if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float); + pd_bind(&x->x_obj.ob_pd, pd_this->pd_midi->m_pgmin_sym); + return (x); +} + +static void pgmin_list(t_pgmin *x, t_symbol *s, int argc, t_atom *argv) +{ + t_float value = atom_getfloatarg(0, argc, argv); + t_float channel = atom_getfloatarg(1, argc, argv); + if (x->x_channel != 0) + { + if (channel != x->x_channel) return; + outlet_float(x->x_outlet1, value); + } + else + { + outlet_float(x->x_outlet2, channel); + outlet_float(x->x_outlet1, value); + } +} + +static void pgmin_free(t_pgmin *x) +{ + pd_unbind(&x->x_obj.ob_pd, pd_this->pd_midi->m_pgmin_sym); +} + +static void pgmin_setup(void) +{ + pgmin_class = class_new(gensym("pgmin"), (t_newmethod)pgmin_new, + (t_method)pgmin_free, sizeof(t_pgmin), + CLASS_NOINLET, A_DEFFLOAT, 0); + class_addlist(pgmin_class, pgmin_list); + class_sethelpsymbol(pgmin_class, gensym("midi")); +} + +void inmidi_programchange(int portno, int channel, int value) +{ + if (pd_this->pd_midi->m_pgmin_sym->s_thing) + { + t_atom at[2]; + SETFLOAT(at, value + 1); + SETFLOAT(at+1, (channel + (portno << 4) + 1)); + pd_list(pd_this->pd_midi->m_pgmin_sym->s_thing, &s_list, 2, at); + } +} + +/* ----------------------- bendin ------------------------- */ + +static t_class *bendin_class; + +typedef struct _bendin +{ + t_object x_obj; + t_float x_channel; + t_outlet *x_outlet1; + t_outlet *x_outlet2; +} t_bendin; + +static void *bendin_new(t_floatarg f) +{ + t_bendin *x = (t_bendin *)pd_new(bendin_class); + x->x_channel = f; + x->x_outlet1 = outlet_new(&x->x_obj, &s_float); + if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float); + pd_bind(&x->x_obj.ob_pd, pd_this->pd_midi->m_bendin_sym); + return (x); +} + +static void bendin_list(t_bendin *x, t_symbol *s, int argc, t_atom *argv) +{ + t_float value = atom_getfloatarg(0, argc, argv); + t_float channel = atom_getfloatarg(1, argc, argv); + if (x->x_channel != 0) + { + if (channel != x->x_channel) return; + outlet_float(x->x_outlet1, value); + } + else + { + outlet_float(x->x_outlet2, channel); + outlet_float(x->x_outlet1, value); + } +} + +static void bendin_free(t_bendin *x) +{ + pd_unbind(&x->x_obj.ob_pd, pd_this->pd_midi->m_bendin_sym); +} + +static void bendin_setup(void) +{ + bendin_class = class_new(gensym("bendin"), (t_newmethod)bendin_new, + (t_method)bendin_free, sizeof(t_bendin), CLASS_NOINLET, A_DEFFLOAT, 0); + class_addlist(bendin_class, bendin_list); + class_sethelpsymbol(bendin_class, gensym("midi")); +} + +void inmidi_pitchbend(int portno, int channel, int value) +{ + if (pd_this->pd_midi->m_bendin_sym->s_thing) + { + t_atom at[2]; + SETFLOAT(at, value); + SETFLOAT(at+1, (channel + (portno << 4) + 1)); + pd_list(pd_this->pd_midi->m_bendin_sym->s_thing, &s_list, 2, at); + } +} + +/* ----------------------- touchin ------------------------- */ + +static t_class *touchin_class; + +typedef struct _touchin +{ + t_object x_obj; + t_float x_channel; + t_outlet *x_outlet1; + t_outlet *x_outlet2; +} t_touchin; + +static void *touchin_new(t_floatarg f) +{ + t_touchin *x = (t_touchin *)pd_new(touchin_class); + x->x_channel = f; + x->x_outlet1 = outlet_new(&x->x_obj, &s_float); + if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float); + pd_bind(&x->x_obj.ob_pd, pd_this->pd_midi->m_touchin_sym); + return (x); +} + +static void touchin_list(t_touchin *x, t_symbol *s, int argc, t_atom *argv) +{ + t_float value = atom_getfloatarg(0, argc, argv); + t_float channel = atom_getfloatarg(1, argc, argv); + if (x->x_channel) + { + if (channel != x->x_channel) return; + outlet_float(x->x_outlet1, value); + } + else + { + outlet_float(x->x_outlet2, channel); + outlet_float(x->x_outlet1, value); + } +} + +static void touchin_free(t_touchin *x) +{ + pd_unbind(&x->x_obj.ob_pd, pd_this->pd_midi->m_touchin_sym); +} + +static void touchin_setup(void) +{ + touchin_class = class_new(gensym("touchin"), (t_newmethod)touchin_new, + (t_method)touchin_free, sizeof(t_touchin), + CLASS_NOINLET, A_DEFFLOAT, 0); + class_addlist(touchin_class, touchin_list); + class_sethelpsymbol(touchin_class, gensym("midi")); +} + +void inmidi_aftertouch(int portno, int channel, int value) +{ + if (pd_this->pd_midi->m_touchin_sym->s_thing) + { + t_atom at[2]; + SETFLOAT(at, value); + SETFLOAT(at+1, (channel + (portno << 4) + 1)); + pd_list(pd_this->pd_midi->m_touchin_sym->s_thing, &s_list, 2, at); + } +} + +/* ----------------------- polytouchin ------------------------- */ + +static t_class *polytouchin_class; + +typedef struct _polytouchin +{ + t_object x_obj; + t_float x_channel; + t_outlet *x_outlet1; + t_outlet *x_outlet2; + t_outlet *x_outlet3; +} t_polytouchin; + +static void *polytouchin_new(t_floatarg f) +{ + t_polytouchin *x = (t_polytouchin *)pd_new(polytouchin_class); + x->x_channel = f; + x->x_outlet1 = outlet_new(&x->x_obj, &s_float); + x->x_outlet2 = outlet_new(&x->x_obj, &s_float); + if (f == 0) x->x_outlet3 = outlet_new(&x->x_obj, &s_float); + pd_bind(&x->x_obj.ob_pd, pd_this->pd_midi->m_polytouchin_sym); + return (x); +} + +static void polytouchin_list(t_polytouchin *x, t_symbol *s, int argc, + t_atom *argv) +{ + t_float pitch = atom_getfloatarg(0, argc, argv); + t_float value = atom_getfloatarg(1, argc, argv); + t_float channel = atom_getfloatarg(2, argc, argv); + if (x->x_channel != 0) + { + if (channel != x->x_channel) return; + outlet_float(x->x_outlet2, pitch); + outlet_float(x->x_outlet1, value); + } + else + { + outlet_float(x->x_outlet3, channel); + outlet_float(x->x_outlet2, pitch); + outlet_float(x->x_outlet1, value); + } +} + +static void polytouchin_free(t_polytouchin *x) +{ + pd_unbind(&x->x_obj.ob_pd, pd_this->pd_midi->m_polytouchin_sym); +} + +static void polytouchin_setup(void) +{ + polytouchin_class = class_new(gensym("polytouchin"), + (t_newmethod)polytouchin_new, (t_method)polytouchin_free, + sizeof(t_polytouchin), CLASS_NOINLET, A_DEFFLOAT, 0); + class_addlist(polytouchin_class, polytouchin_list); + class_sethelpsymbol(polytouchin_class, gensym("midi")); +} + +void inmidi_polyaftertouch(int portno, int channel, int pitch, int value) +{ + if (pd_this->pd_midi->m_polytouchin_sym->s_thing) + { + t_atom at[3]; + SETFLOAT(at, pitch); + SETFLOAT(at+1, value); + SETFLOAT(at+2, (channel + (portno << 4) + 1)); + pd_list(pd_this->pd_midi->m_polytouchin_sym->s_thing, &s_list, 3, at); + } +} + +/*----------midirealtimein (midi F8,FA,FB,FC,FE,FF message)-----------------*/ + +static t_class *midirealtimein_class; + +typedef struct _midirealtimein +{ + t_object x_obj; + t_outlet *x_outlet1; + t_outlet *x_outlet2; +} t_midirealtimein; + +static void *midirealtimein_new(void) +{ + t_midirealtimein *x = (t_midirealtimein *)pd_new(midirealtimein_class); + x->x_outlet1 = outlet_new(&x->x_obj, &s_float); + x->x_outlet2 = outlet_new(&x->x_obj, &s_float); + pd_bind(&x->x_obj.ob_pd, pd_this->pd_midi->m_midirealtimein_sym); + return (x); +} + +static void midirealtimein_list(t_midirealtimein *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_float portno = atom_getfloatarg(0, argc, argv); + t_float byte = atom_getfloatarg(1, argc, argv); + + outlet_float(x->x_outlet2, portno); + outlet_float(x->x_outlet1, byte); +} + +static void midirealtimein_free(t_midirealtimein *x) +{ + pd_unbind(&x->x_obj.ob_pd, pd_this->pd_midi->m_midirealtimein_sym); +} + +static void midirealtimein_setup(void) +{ + midirealtimein_class = class_new(gensym("midirealtimein"), + (t_newmethod)midirealtimein_new, (t_method)midirealtimein_free, + sizeof(t_midirealtimein), CLASS_NOINLET, A_DEFFLOAT, 0); + class_addlist(midirealtimein_class, midirealtimein_list); + class_sethelpsymbol(midirealtimein_class, gensym("midi")); +} + +void inmidi_realtimein(int portno, int SysMsg) +{ + if (pd_this->pd_midi->m_midirealtimein_sym->s_thing) + { + t_atom at[2]; + SETFLOAT(at, portno); + SETFLOAT(at+1, SysMsg); + pd_list(pd_this->pd_midi->m_midirealtimein_sym->s_thing, &s_list, 2, at); + } +} + +/* -------------------------- midiout -------------------------- */ + +static t_class *midiout_class; + +void sys_putmidibyte(int portno, int byte); + +typedef struct _midiout +{ + t_object x_obj; + t_float x_portno; +} t_midiout; + +static void *midiout_new(t_floatarg portno) +{ + t_midiout *x = (t_midiout *)pd_new(midiout_class); + if (portno <= 0) portno = 1; + x->x_portno = portno; + floatinlet_new(&x->x_obj, &x->x_portno); + return (x); +} + +static void midiout_float(t_midiout *x, t_floatarg f) +{ + outmidi_byte(x->x_portno - 1, f); +} + +static void midiout_list(t_midiout *x, t_symbol *s, int ac, t_atom *av) +{ + int i; + for (i = 0; i < ac; ++i) + { + if(av[i].a_type == A_FLOAT) + outmidi_byte(x->x_portno - 1, av[i].a_w.w_float); + } +} + +static void midiout_setup(void) +{ + midiout_class = class_new(gensym("midiout"), (t_newmethod)midiout_new, 0, + sizeof(t_midiout), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addfloat(midiout_class, midiout_float); + class_addlist(midiout_class, midiout_list); + class_sethelpsymbol(midiout_class, gensym("midi")); +} + +/* -------------------------- noteout -------------------------- */ + +static t_class *noteout_class; + +typedef struct _noteout +{ + t_object x_obj; + t_float x_velo; + t_float x_channel; +} t_noteout; + +static void *noteout_new(t_floatarg channel) +{ + t_noteout *x = (t_noteout *)pd_new(noteout_class); + x->x_velo = 0; + if (channel < 1) channel = 1; + x->x_channel = channel; + floatinlet_new(&x->x_obj, &x->x_velo); + floatinlet_new(&x->x_obj, &x->x_channel); + return (x); +} + +static void noteout_float(t_noteout *x, t_float f) +{ + int binchan = x->x_channel - 1; + if (binchan < 0) + binchan = 0; + outmidi_noteon((binchan >> 4), + (binchan & 15), (int)f, (int)x->x_velo); +} + +static void noteout_setup(void) +{ + noteout_class = class_new(gensym("noteout"), (t_newmethod)noteout_new, 0, + sizeof(t_noteout), 0, A_DEFFLOAT, 0); + class_addfloat(noteout_class, noteout_float); + class_sethelpsymbol(noteout_class, gensym("midi")); +} + + +/* -------------------------- ctlout -------------------------- */ + +static t_class *ctlout_class; + +typedef struct _ctlout +{ + t_object x_obj; + t_float x_ctl; + t_float x_channel; +} t_ctlout; + +static void *ctlout_new(t_floatarg ctl, t_floatarg channel) +{ + t_ctlout *x = (t_ctlout *)pd_new(ctlout_class); + x->x_ctl = ctl; + if (channel <= 0) channel = 1; + x->x_channel = channel; + floatinlet_new(&x->x_obj, &x->x_ctl); + floatinlet_new(&x->x_obj, &x->x_channel); + return (x); +} + +static void ctlout_float(t_ctlout *x, t_float f) +{ + int binchan = x->x_channel - 1; + if (binchan < 0) + binchan = 0; + outmidi_controlchange((binchan >> 4), + (binchan & 15), (int)(x->x_ctl), (int)f); +} + +static void ctlout_setup(void) +{ + ctlout_class = class_new(gensym("ctlout"), (t_newmethod)ctlout_new, 0, + sizeof(t_ctlout), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addfloat(ctlout_class, ctlout_float); + class_sethelpsymbol(ctlout_class, gensym("midi")); +} + + +/* -------------------------- pgmout -------------------------- */ + +static t_class *pgmout_class; + +typedef struct _pgmout +{ + t_object x_obj; + t_float x_channel; +} t_pgmout; + +static void *pgmout_new(t_floatarg channel) +{ + t_pgmout *x = (t_pgmout *)pd_new(pgmout_class); + if (channel <= 0) channel = 1; + x->x_channel = channel; + floatinlet_new(&x->x_obj, &x->x_channel); + return (x); +} + +static void pgmout_float(t_pgmout *x, t_floatarg f) +{ + int binchan = x->x_channel - 1; + int n = f - 1; + if (binchan < 0) + binchan = 0; + if (n < 0) n = 0; + else if (n > 127) n = 127; + outmidi_programchange((binchan >> 4), + (binchan & 15), n); +} + +static void pgmout_setup(void) +{ + pgmout_class = class_new(gensym("pgmout"), (t_newmethod)pgmout_new, 0, + sizeof(t_pgmout), 0, A_DEFFLOAT, 0); + class_addfloat(pgmout_class, pgmout_float); + class_sethelpsymbol(pgmout_class, gensym("midi")); +} + + +/* -------------------------- bendout -------------------------- */ + +static t_class *bendout_class; + +typedef struct _bendout +{ + t_object x_obj; + t_float x_channel; +} t_bendout; + +static void *bendout_new(t_floatarg channel) +{ + t_bendout *x = (t_bendout *)pd_new(bendout_class); + if (channel <= 0) channel = 1; + x->x_channel = channel; + floatinlet_new(&x->x_obj, &x->x_channel); + return (x); +} + +static void bendout_float(t_bendout *x, t_float f) +{ + int binchan = x->x_channel - 1; + int n = (int)f + 8192; + if (binchan < 0) + binchan = 0; + outmidi_pitchbend((binchan >> 4), (binchan & 15), n); +} + +static void bendout_setup(void) +{ + bendout_class = class_new(gensym("bendout"), (t_newmethod)bendout_new, 0, + sizeof(t_bendout), 0, A_DEFFLOAT, 0); + class_addfloat(bendout_class, bendout_float); + class_sethelpsymbol(bendout_class, gensym("midi")); +} + +/* -------------------------- touch -------------------------- */ + +static t_class *touchout_class; + +typedef struct _touchout +{ + t_object x_obj; + t_float x_channel; +} t_touchout; + +static void *touchout_new(t_floatarg channel) +{ + t_touchout *x = (t_touchout *)pd_new(touchout_class); + if (channel <= 0) channel = 1; + x->x_channel = channel; + floatinlet_new(&x->x_obj, &x->x_channel); + return (x); +} + +static void touchout_float(t_touchout *x, t_float f) +{ + int binchan = x->x_channel - 1; + if (binchan < 0) + binchan = 0; + outmidi_aftertouch((binchan >> 4), (binchan & 15), (int)f); +} + +static void touchout_setup(void) +{ + touchout_class = class_new(gensym("touchout"), (t_newmethod)touchout_new, 0, + sizeof(t_touchout), 0, A_DEFFLOAT, 0); + class_addfloat(touchout_class, touchout_float); + class_sethelpsymbol(touchout_class, gensym("midi")); +} + +/* -------------------------- polytouch -------------------------- */ + +static t_class *polytouchout_class; + +typedef struct _polytouchout +{ + t_object x_obj; + t_float x_channel; + t_float x_pitch; +} t_polytouchout; + +static void *polytouchout_new(t_floatarg channel) +{ + t_polytouchout *x = (t_polytouchout *)pd_new(polytouchout_class); + if (channel <= 0) channel = 1; + x->x_channel = channel; + x->x_pitch = 0; + floatinlet_new(&x->x_obj, &x->x_pitch); + floatinlet_new(&x->x_obj, &x->x_channel); + return (x); +} + +static void polytouchout_float(t_polytouchout *x, t_float n) +{ + int binchan = x->x_channel - 1; + if (binchan < 0) + binchan = 0; + outmidi_polyaftertouch((binchan >> 4), (binchan & 15), x->x_pitch, n); +} + +static void polytouchout_setup(void) +{ + polytouchout_class = class_new(gensym("polytouchout"), + (t_newmethod)polytouchout_new, 0, + sizeof(t_polytouchout), 0, A_DEFFLOAT, 0); + class_addfloat(polytouchout_class, polytouchout_float); + class_sethelpsymbol(polytouchout_class, gensym("midi")); +} + +/* -------------------------- makenote -------------------------- */ + +static t_class *makenote_class; + +typedef struct _hang +{ + t_clock *h_clock; + struct _hang *h_next; + t_float h_pitch; + struct _makenote *h_owner; +} t_hang; + +typedef struct _makenote +{ + t_object x_obj; + t_float x_velo; + t_float x_dur; + t_outlet *x_pitchout; + t_outlet *x_velout; + t_hang *x_hang; +} t_makenote; + +static void *makenote_new(t_floatarg velo, t_floatarg dur) +{ + t_makenote *x = (t_makenote *)pd_new(makenote_class); + x->x_velo = velo; + x->x_dur = dur; + floatinlet_new(&x->x_obj, &x->x_velo); + floatinlet_new(&x->x_obj, &x->x_dur); + x->x_pitchout = outlet_new(&x->x_obj, &s_float); + x->x_velout = outlet_new(&x->x_obj, &s_float); + x->x_hang = 0; + return (x); +} + +static void makenote_tick(t_hang *hang) +{ + t_makenote *x = hang->h_owner; + t_hang *h2, *h3; + outlet_float(x->x_velout, 0); + outlet_float(x->x_pitchout, hang->h_pitch); + if (x->x_hang == hang) x->x_hang = hang->h_next; + else for (h2 = x->x_hang; (h3 = h2->h_next); h2 = h3) + { + if (h3 == hang) + { + h2->h_next = h3->h_next; + break; + } + } + clock_free(hang->h_clock); + freebytes(hang, sizeof(*hang)); +} + +static void makenote_float(t_makenote *x, t_float f) +{ + t_hang *hang; + if (!x->x_velo) return; + outlet_float(x->x_velout, x->x_velo); + outlet_float(x->x_pitchout, f); + hang = (t_hang *)getbytes(sizeof *hang); + hang->h_next = x->x_hang; + x->x_hang = hang; + hang->h_pitch = f; + hang->h_owner = x; + hang->h_clock = clock_new(hang, (t_method)makenote_tick); + clock_delay(hang->h_clock, (x->x_dur >= 0 ? x->x_dur : 0)); +} + +static void makenote_stop(t_makenote *x) +{ + t_hang *hang; + while ((hang = x->x_hang)) + { + outlet_float(x->x_velout, 0); + outlet_float(x->x_pitchout, hang->h_pitch); + x->x_hang = hang->h_next; + clock_free(hang->h_clock); + freebytes(hang, sizeof(*hang)); + } +} + +static void makenote_clear(t_makenote *x) +{ + t_hang *hang; + while ((hang = x->x_hang)) + { + x->x_hang = hang->h_next; + clock_free(hang->h_clock); + freebytes(hang, sizeof(*hang)); + } +} + +static void makenote_setup(void) +{ + makenote_class = class_new(gensym("makenote"), + (t_newmethod)makenote_new, (t_method)makenote_clear, + sizeof(t_makenote), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addfloat(makenote_class, makenote_float); + class_addmethod(makenote_class, (t_method)makenote_stop, gensym("stop"), + 0); + class_addmethod(makenote_class, (t_method)makenote_clear, gensym("clear"), + 0); +} + +/* -------------------------- stripnote -------------------------- */ + +static t_class *stripnote_class; + +typedef struct _stripnote +{ + t_object x_obj; + t_float x_velo; + t_outlet *x_pitchout; + t_outlet *x_velout; +} t_stripnote; + +static void *stripnote_new(void) +{ + t_stripnote *x = (t_stripnote *)pd_new(stripnote_class); + floatinlet_new(&x->x_obj, &x->x_velo); + x->x_pitchout = outlet_new(&x->x_obj, &s_float); + x->x_velout = outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void stripnote_float(t_stripnote *x, t_float f) +{ + t_hang *hang; + if (!x->x_velo) return; + outlet_float(x->x_velout, x->x_velo); + outlet_float(x->x_pitchout, f); +} + +static void stripnote_setup(void) +{ + stripnote_class = class_new(gensym("stripnote"), + (t_newmethod)stripnote_new, 0, sizeof(t_stripnote), 0, 0); + class_addfloat(stripnote_class, stripnote_float); +} + +/* -------------------------- poly -------------------------- */ + +static t_class *poly_class; + +typedef struct voice +{ + t_float v_pitch; + int v_used; + unsigned long v_serial; +} t_voice; + +typedef struct poly +{ + t_object x_obj; + int x_n; + t_voice *x_vec; + t_float x_vel; + t_outlet *x_pitchout; + t_outlet *x_velout; + unsigned long x_serial; + int x_steal; +} t_poly; + +static void *poly_new(t_float fnvoice, t_float fsteal) +{ + int i, n = fnvoice; + t_poly *x = (t_poly *)pd_new(poly_class); + t_voice *v; + if (n < 1) n = 1; + x->x_n = n; + x->x_vec = (t_voice *)getbytes(n * sizeof(*x->x_vec)); + for (v = x->x_vec, i = n; i--; v++) + v->v_pitch = v->v_used = v->v_serial = 0; + x->x_vel = 0; + x->x_steal = (fsteal != 0); + floatinlet_new(&x->x_obj, &x->x_vel); + outlet_new(&x->x_obj, &s_float); + x->x_pitchout = outlet_new(&x->x_obj, &s_float); + x->x_velout = outlet_new(&x->x_obj, &s_float); + x->x_serial = 0; + return (x); +} + +static void poly_float(t_poly *x, t_float f) +{ + int i; + t_voice *v; + t_voice *firston, *firstoff; + unsigned int serialon, serialoff, onindex = 0, offindex = 0; + if (x->x_vel > 0) + { + /* note on. Look for a vacant voice */ + for (v = x->x_vec, i = 0, firston = firstoff = 0, + serialon = serialoff = 0xffffffff; i < x->x_n; v++, i++) + { + if (v->v_used && v->v_serial < serialon) + firston = v, serialon = (unsigned int)v->v_serial, onindex = i; + else if (!v->v_used && v->v_serial < serialoff) + firstoff = v, serialoff = (unsigned int)v->v_serial, offindex = i; + } + if (firstoff) + { + outlet_float(x->x_velout, x->x_vel); + outlet_float(x->x_pitchout, firstoff->v_pitch = f); + outlet_float(x->x_obj.ob_outlet, offindex+1); + firstoff->v_used = 1; + firstoff->v_serial = x->x_serial++; + } + /* if none, steal one */ + else if (firston && x->x_steal) + { + outlet_float(x->x_velout, 0); + outlet_float(x->x_pitchout, firston->v_pitch); + outlet_float(x->x_obj.ob_outlet, onindex+1); + outlet_float(x->x_velout, x->x_vel); + outlet_float(x->x_pitchout, firston->v_pitch = f); + outlet_float(x->x_obj.ob_outlet, onindex+1); + firston->v_serial = x->x_serial++; + } + } + else /* note off. Turn off oldest match */ + { + for (v = x->x_vec, i = 0, firston = 0, serialon = 0xffffffff; + i < x->x_n; v++, i++) + if (v->v_used && v->v_pitch == f && v->v_serial < serialon) + firston = v, serialon = (unsigned int)v->v_serial, onindex = i; + if (firston) + { + firston->v_used = 0; + firston->v_serial = x->x_serial++; + outlet_float(x->x_velout, 0); + outlet_float(x->x_pitchout, firston->v_pitch); + outlet_float(x->x_obj.ob_outlet, onindex+1); + } + } +} + +static void poly_stop(t_poly *x) +{ + int i; + t_voice *v; + for (i = 0, v = x->x_vec; i < x->x_n; i++, v++) + if (v->v_used) + { + outlet_float(x->x_velout, 0L); + outlet_float(x->x_pitchout, v->v_pitch); + outlet_float(x->x_obj.ob_outlet, i+1); + v->v_used = 0; + v->v_serial = x->x_serial++; + } +} + +static void poly_clear(t_poly *x) +{ + int i; + t_voice *v; + for (v = x->x_vec, i = x->x_n; i--; v++) v->v_used = v->v_serial = 0; +} + +static void poly_free(t_poly *x) +{ + freebytes(x->x_vec, x->x_n * sizeof (*x->x_vec)); +} + +static void poly_setup(void) +{ + poly_class = class_new(gensym("poly"), + (t_newmethod)poly_new, (t_method)poly_free, + sizeof(t_poly), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addfloat(poly_class, poly_float); + class_addmethod(poly_class, (t_method)poly_stop, gensym("stop"), 0); + class_addmethod(poly_class, (t_method)poly_clear, gensym("clear"), 0); +} + +/* -------------------------- bag -------------------------- */ + +static t_class *bag_class; + +typedef struct _bagelem +{ + struct _bagelem *e_next; + t_float e_value; +} t_bagelem; + +typedef struct _bag +{ + t_object x_obj; + t_float x_velo; + t_bagelem *x_first; +} t_bag; + +static void *bag_new(void) +{ + t_bag *x = (t_bag *)pd_new(bag_class); + x->x_velo = 0; + floatinlet_new(&x->x_obj, &x->x_velo); + outlet_new(&x->x_obj, &s_float); + x->x_first = 0; + return (x); +} + +static void bag_float(t_bag *x, t_float f) +{ + t_bagelem *bagelem, *e2, *e3; + if (x->x_velo != 0) + { + bagelem = (t_bagelem *)getbytes(sizeof *bagelem); + bagelem->e_next = 0; + bagelem->e_value = f; + if (!x->x_first) x->x_first = bagelem; + else /* LATER replace with a faster algorithm */ + { + for (e2 = x->x_first; (e3 = e2->e_next); e2 = e3) + ; + e2->e_next = bagelem; + } + } + else + { + if (!x->x_first) return; + if (x->x_first->e_value == f) + { + bagelem = x->x_first; + x->x_first = x->x_first->e_next; + freebytes(bagelem, sizeof(*bagelem)); + return; + } + for (e2 = x->x_first; (e3 = e2->e_next); e2 = e3) + if (e3->e_value == f) + { + e2->e_next = e3->e_next; + freebytes(e3, sizeof(*e3)); + return; + } + } +} + +static void bag_flush(t_bag *x) +{ + t_bagelem *bagelem; + while ((bagelem = x->x_first)) + { + outlet_float(x->x_obj.ob_outlet, bagelem->e_value); + x->x_first = bagelem->e_next; + freebytes(bagelem, sizeof(*bagelem)); + } +} + +static void bag_clear(t_bag *x) +{ + t_bagelem *bagelem; + while ((bagelem = x->x_first)) + { + x->x_first = bagelem->e_next; + freebytes(bagelem, sizeof(*bagelem)); + } +} + +static void bag_setup(void) +{ + bag_class = class_new(gensym("bag"), + (t_newmethod)bag_new, (t_method)bag_clear, + sizeof(t_bag), 0, 0); + class_addfloat(bag_class, bag_float); + class_addmethod(bag_class, (t_method)bag_flush, gensym("flush"), 0); + class_addmethod(bag_class, (t_method)bag_clear, gensym("clear"), 0); +} + +void x_midi_setup(void) +{ + midiin_setup(); + midirealtimein_setup(); + notein_setup(); + ctlin_setup(); + pgmin_setup(); + bendin_setup(); + touchin_setup(); + polytouchin_setup(); + midiout_setup(); + noteout_setup(); + ctlout_setup(); + pgmout_setup(); + bendout_setup(); + touchout_setup(); + polytouchout_setup(); + makenote_setup(); + stripnote_setup(); + poly_setup(); + bag_setup(); +} + +void x_midi_newpdinstance(void) +{ + pd_this->pd_midi = getbytes(sizeof(t_instancemidi)); + pd_this->pd_midi->m_midiin_sym = gensym("#midiin"); + pd_this->pd_midi->m_sysexin_sym = gensym("#sysexin"); + pd_this->pd_midi->m_notein_sym = gensym("#notein"); + pd_this->pd_midi->m_ctlin_sym = gensym("#ctlin"); + pd_this->pd_midi->m_pgmin_sym = gensym("#pgmin"); + pd_this->pd_midi->m_bendin_sym = gensym("#bendin"); + pd_this->pd_midi->m_touchin_sym = gensym("#touchin"); + pd_this->pd_midi->m_polytouchin_sym = gensym("#polytouchin"); + pd_this->pd_midi->m_midirealtimein_sym = gensym("#midirealtimein"); +} + +void x_midi_freepdinstance(void) +{ + freebytes(pd_this->pd_midi, sizeof(t_instancemidi)); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/x_misc.c b/ports/camomile/source/LibPd/pure-data/src/x_misc.c new file mode 100644 index 00000000..f2704651 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_misc.c @@ -0,0 +1,859 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* misc. */ + +#include "m_pd.h" +#include "s_stuff.h" +#include "g_canvas.h" +#include +#include +#include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#endif /* _WIN32 */ + +#if defined (__APPLE__) || defined (__FreeBSD__) +#define CLOCKHZ CLK_TCK +#endif +#if defined (__linux__) || defined (__CYGWIN__) || defined (ANDROID) +#define CLOCKHZ sysconf(_SC_CLK_TCK) +#endif +#if defined (__FreeBSD_kernel__) || defined(__GNU__) || defined(__OpenBSD__) +#include +#define CLOCKHZ CLOCKS_PER_SEC +#endif + +#ifdef _WIN32 +# include /* MSVC or mingw on windows */ +#elif defined(__linux__) || defined(__APPLE__) +# include /* linux, mac, mingw, cygwin */ +#else +# include /* BSDs for example */ +#endif + +/* -------------------------- random ------------------------------ */ +/* this is strictly homebrew and untested. */ + +static t_class *random_class; + +typedef struct _random +{ + t_object x_obj; + t_float x_f; + unsigned int x_state; +} t_random; + + +static int makeseed(void) +{ + static unsigned int random_nextseed = 1489853723; + random_nextseed = random_nextseed * 435898247 + 938284287; + return (random_nextseed & 0x7fffffff); +} + +static void *random_new(t_floatarg f) +{ + t_random *x = (t_random *)pd_new(random_class); + x->x_f = f; + x->x_state = makeseed(); + floatinlet_new(&x->x_obj, &x->x_f); + outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void random_bang(t_random *x) +{ + int n = x->x_f, nval; + int range = (n < 1 ? 1 : n); + unsigned int randval = x->x_state; + x->x_state = randval = randval * 472940017 + 832416023; + nval = ((double)range) * ((double)randval) + * (1./4294967296.); + if (nval >= range) nval = range-1; + outlet_float(x->x_obj.ob_outlet, nval); +} + +static void random_seed(t_random *x, t_float f, t_float glob) +{ + x->x_state = f; +} + +static void random_setup(void) +{ + random_class = class_new(gensym("random"), (t_newmethod)random_new, 0, + sizeof(t_random), 0, A_DEFFLOAT, 0); + class_addbang(random_class, random_bang); + class_addmethod(random_class, (t_method)random_seed, + gensym("seed"), A_FLOAT, 0); +} + + +/* -------------------------- loadbang ------------------------------ */ +static t_class *loadbang_class; + +typedef struct _loadbang +{ + t_object x_obj; +} t_loadbang; + +static void *loadbang_new(void) +{ + t_loadbang *x = (t_loadbang *)pd_new(loadbang_class); + outlet_new(&x->x_obj, &s_bang); + return (x); +} + +static void loadbang_loadbang(t_loadbang *x, t_floatarg action) +{ + if (action == LB_LOAD) + outlet_bang(x->x_obj.ob_outlet); +} + +static void loadbang_setup(void) +{ + loadbang_class = class_new(gensym("loadbang"), (t_newmethod)loadbang_new, 0, + sizeof(t_loadbang), CLASS_NOINLET, 0); + class_addmethod(loadbang_class, (t_method)loadbang_loadbang, + gensym("loadbang"), A_DEFFLOAT, 0); +} + +/* ------------- namecanvas (delete this later) --------------------- */ +static t_class *namecanvas_class; + +typedef struct _namecanvas +{ + t_object x_obj; + t_symbol *x_sym; + t_pd *x_owner; +} t_namecanvas; + +static void *namecanvas_new(t_symbol *s) +{ + t_namecanvas *x = (t_namecanvas *)pd_new(namecanvas_class); + x->x_owner = (t_pd *)canvas_getcurrent(); + x->x_sym = s; + if (*s->s_name) pd_bind(x->x_owner, s); + return (x); +} + +static void namecanvas_free(t_namecanvas *x) +{ + if (*x->x_sym->s_name) pd_unbind(x->x_owner, x->x_sym); +} + +static void namecanvas_setup(void) +{ + namecanvas_class = class_new(gensym("namecanvas"), + (t_newmethod)namecanvas_new, (t_method)namecanvas_free, + sizeof(t_namecanvas), CLASS_NOINLET, A_DEFSYM, 0); +} + +/* -------------------------- cputime ------------------------------ */ + +static t_class *cputime_class; + +typedef struct _cputime +{ + t_object x_obj; +#ifdef _WIN32 + LARGE_INTEGER x_kerneltime; + LARGE_INTEGER x_usertime; + int x_warned; +#else + struct tms x_setcputime; +#endif /* _WIN32 */ +} t_cputime; + +static void cputime_bang(t_cputime *x) +{ +#ifdef _WIN32 + FILETIME ignorethis, ignorethat; + BOOL retval; + retval = GetProcessTimes(GetCurrentProcess(), &ignorethis, &ignorethat, + (FILETIME *)&x->x_kerneltime, (FILETIME *)&x->x_usertime); + if (!retval) + { + if (!x->x_warned) + post("cputime is apparently not supported on your platform"); + x->x_warned = 1; + x->x_kerneltime.QuadPart = 0; + x->x_usertime.QuadPart = 0; + } +#else + times(&x->x_setcputime); +#endif /* _WIN32 */ +} + +static void cputime_bang2(t_cputime *x) +{ +#ifndef _WIN32 + t_float elapsedcpu; + struct tms newcputime; + times(&newcputime); + elapsedcpu = 1000 * ( + newcputime.tms_utime + newcputime.tms_stime - + x->x_setcputime.tms_utime - x->x_setcputime.tms_stime) / CLOCKHZ; + outlet_float(x->x_obj.ob_outlet, elapsedcpu); +#else + t_float elapsedcpu; + FILETIME ignorethis, ignorethat; + LARGE_INTEGER usertime, kerneltime; + BOOL retval; + + retval = GetProcessTimes(GetCurrentProcess(), &ignorethis, &ignorethat, + (FILETIME *)&kerneltime, (FILETIME *)&usertime); + if (retval) + elapsedcpu = 0.0001 * + ((kerneltime.QuadPart - x->x_kerneltime.QuadPart) + + (usertime.QuadPart - x->x_usertime.QuadPart)); + else elapsedcpu = 0; + outlet_float(x->x_obj.ob_outlet, elapsedcpu); +#endif /* NOT _WIN32 */ +} + +static void *cputime_new(void) +{ + t_cputime *x = (t_cputime *)pd_new(cputime_class); + outlet_new(&x->x_obj, gensym("float")); + + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("bang"), gensym("bang2")); +#ifdef _WIN32 + x->x_warned = 0; +#endif + cputime_bang(x); + return (x); +} + +static void cputime_setup(void) +{ + cputime_class = class_new(gensym("cputime"), (t_newmethod)cputime_new, 0, + sizeof(t_cputime), 0, 0); + class_addbang(cputime_class, cputime_bang); + class_addmethod(cputime_class, (t_method)cputime_bang2, gensym("bang2"), 0); +} + +/* -------------------------- realtime ------------------------------ */ + +static t_class *realtime_class; + +typedef struct _realtime +{ + t_object x_obj; + double x_setrealtime; +} t_realtime; + +static void realtime_bang(t_realtime *x) +{ + x->x_setrealtime = sys_getrealtime(); +} + +static void realtime_bang2(t_realtime *x) +{ + outlet_float(x->x_obj.ob_outlet, + (sys_getrealtime() - x->x_setrealtime) * 1000.); +} + +static void *realtime_new(void) +{ + t_realtime *x = (t_realtime *)pd_new(realtime_class); + outlet_new(&x->x_obj, gensym("float")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("bang"), gensym("bang2")); + realtime_bang(x); + return (x); +} + +static void realtime_setup(void) +{ + realtime_class = class_new(gensym("realtime"), (t_newmethod)realtime_new, 0, + sizeof(t_realtime), 0, 0); + class_addbang(realtime_class, realtime_bang); + class_addmethod(realtime_class, (t_method)realtime_bang2, gensym("bang2"), + 0); +} + +/* ---------- oscparse - parse simple OSC messages ----------------- */ + +static t_class *oscparse_class; + +typedef struct _oscparse +{ + t_object x_obj; +} t_oscparse; + +#define ROUNDUPTO4(x) (((x) + 3) & (~3)) + +#define READINT(x) ((((int)(((x) )->a_w.w_float)) & 0xff) << 24) | \ + ((((int)(((x)+1)->a_w.w_float)) & 0xff) << 16) | \ + ((((int)(((x)+2)->a_w.w_float)) & 0xff) << 8) | \ + ((((int)(((x)+3)->a_w.w_float)) & 0xff) << 0) + +static t_symbol *grabstring(int argc, t_atom *argv, int *ip, int slash) +{ + char buf[MAXPDSTRING]; + int first, nchar; + if (slash) + while (*ip < argc && argv[*ip].a_w.w_float == '/') + (*ip)++; + for (nchar = 0; nchar < MAXPDSTRING-1 && *ip < argc; nchar++, (*ip)++) + { + char c = argv[*ip].a_w.w_float; + if (c == 0 || (slash && c == '/')) + break; + buf[nchar] = c; + } + buf[nchar] = 0; + if (!slash) + *ip = ROUNDUPTO4(*ip+1); + if (*ip > argc) + *ip = argc; + return (gensym(buf)); +} + +static void oscparse_list(t_oscparse *x, t_symbol *s, int argc, t_atom *argv) +{ + int i, j, j2, k, outc = 1, blob = 0, typeonset, dataonset, nfield; + t_atom *outv; + if (!argc) + return; + for (i = 0; i < argc; i++) + if (argv[i].a_type != A_FLOAT) + { + pd_error(x, "oscparse: takes numbers only"); + return; + } + if (argv[0].a_w.w_float == '#') /* it's a bundle */ + { + if (argv[1].a_w.w_float != 'b' || argc < 16) + { + pd_error(x, "oscparse: malformed bundle"); + return; + } + /* we ignore the timetag since there's no correct way to + convert it to Pd logical time that I can think of. LATER + consider at least outputting timetag differentially converted + into Pd time units. */ + for (i = 16; i < argc-4; ) + { + int msize = READINT(argv+i); + if (msize <= 0 || msize & 3) + { + pd_error(x, "oscparse: bad bundle element size"); + return; + } + oscparse_list(x, 0, msize, argv+i+4); + i += msize+4; + } + return; + } + else if (argv[0].a_w.w_float != '/') + { + pd_error(x, "oscparse: not an OSC message (no leading slash)"); + return; + } + for (i = 1; i < argc && argv[i].a_w.w_float != 0; i++) + if (argv[i].a_w.w_float == '/') + outc++; + i = ROUNDUPTO4(i+1); + if (argv[i].a_w.w_float != ',' || (i+1) >= argc) + { + pd_error(x, "oscparse: malformed type string (char %d, index %d)", + (int)(argv[i].a_w.w_float), i); + return; + } + typeonset = ++i; + for (; i < argc && argv[i].a_w.w_float != 0; i++) + if (argv[i].a_w.w_float == 'b') + blob = 1; + nfield = i - typeonset; + if (blob) + outc += argc - typeonset; + else outc += nfield; + outv = (t_atom *)alloca(outc * sizeof(t_atom)); + dataonset = ROUNDUPTO4(i + 1); + /* post("outc %d, typeonset %d, dataonset %d, nfield %d", outc, typeonset, + dataonset, nfield); */ + for (i = j = 0; i < typeonset-1 && argv[i].a_w.w_float != 0 && + j < outc; j++) + SETSYMBOL(outv+j, grabstring(argc, argv, &i, 1)); + for (i = typeonset, k = dataonset; i < typeonset + nfield; i++) + { + union + { + float z_f; + uint32_t z_i; + } z; + float f; + int blobsize; + switch ((int)(argv[i].a_w.w_float)) + { + case 'f': + if (k > argc - 4) + goto tooshort; + z.z_i = READINT(argv+k); + f = z.z_f; + if (PD_BADFLOAT(f)) + f = 0; + if (j >= outc) + { + bug("oscparse 1: %d >=%d", j, outc); + return; + } + SETFLOAT(outv+j, f); + j++; k += 4; + break; + case 'i': + if (k > argc - 4) + goto tooshort; + if (j >= outc) + { + bug("oscparse 2"); + return; + } + SETFLOAT(outv+j, READINT(argv+k)); + j++; k += 4; + break; + case 's': + if (j >= outc) + { + bug("oscparse 3"); + return; + } + SETSYMBOL(outv+j, grabstring(argc, argv, &k, 0)); + j++; + break; + case 'b': + if (k > argc - 4) + goto tooshort; + blobsize = READINT(argv+k); + k += 4; + if (blobsize < 0 || blobsize > argc - k) + goto tooshort; + if (j + blobsize + 1 > outc) + { + bug("oscparse 4"); + return; + } + if (k + blobsize > argc) + goto tooshort; + SETFLOAT(outv+j, blobsize); + j++; + for (j2 = 0; j2 < blobsize; j++, j2++, k++) + SETFLOAT(outv+j, argv[k].a_w.w_float); + k = ROUNDUPTO4(k); + break; + default: + pd_error(x, "oscparse: unknown tag '%c' (%d)", + (int)(argv[i].a_w.w_float), (int)(argv[i].a_w.w_float)); + } + } + outlet_list(x->x_obj.ob_outlet, 0, j, outv); + return; +tooshort: + pd_error(x, "oscparse: OSC message ended prematurely"); +} + +static t_oscparse *oscparse_new(t_symbol *s, int argc, t_atom *argv) +{ + t_oscparse *x = (t_oscparse *)pd_new(oscparse_class); + outlet_new(&x->x_obj, gensym("list")); + return (x); +} + +void oscparse_setup(void) +{ + oscparse_class = class_new(gensym("oscparse"), (t_newmethod)oscparse_new, + 0, sizeof(t_oscparse), 0, A_GIMME, 0); + class_addlist(oscparse_class, oscparse_list); +} + +/* --------- oscformat - format simple OSC messages -------------- */ +static t_class *oscformat_class; + +typedef struct _oscformat +{ + t_object x_obj; + char *x_pathbuf; + size_t x_pathsize; + t_symbol *x_format; +} t_oscformat; + +static void oscformat_set(t_oscformat *x, t_symbol *s, int argc, t_atom *argv) +{ + char buf[MAXPDSTRING]; + int i; + size_t newsize; + *x->x_pathbuf = 0; + buf[0] = '/'; + for (i = 0; i < argc; i++) + { + char *where = (argv[i].a_type == A_SYMBOL && + *argv[i].a_w.w_symbol->s_name == '/' ? buf : buf+1); + atom_string(&argv[i], where, MAXPDSTRING-1); + if ((newsize = strlen(buf) + strlen(x->x_pathbuf) + 1) > x->x_pathsize) + { + x->x_pathbuf = resizebytes(x->x_pathbuf, x->x_pathsize, newsize); + x->x_pathsize = newsize; + } + strcat(x->x_pathbuf, buf); + } +} + +static void oscformat_format(t_oscformat *x, t_symbol *s) +{ + char *sp; + for (sp = s->s_name; *sp; sp++) + { + if (*sp != 'f' && *sp != 'i' && *sp != 's' && *sp != 'b') + { + pd_error(x, + "oscformat '%s' may only contain 'f', 'i'. 's', and/or 'b'", + sp); + return; + } + } + x->x_format = s; +} + +#define WRITEINT(msg, i) SETFLOAT((msg), (((i) >> 24) & 0xff)); \ + SETFLOAT((msg)+1, (((i) >> 16) & 0xff)); \ + SETFLOAT((msg)+2, (((i) >> 8) & 0xff)); \ + SETFLOAT((msg)+3, (((i) ) & 0xff)) + +static void putstring(t_atom *msg, int *ip, const char *s) +{ + const char *sp = s; + do + { + SETFLOAT(&msg[*ip], *sp & 0xff); + (*ip)++; + } + while (*sp++); + while (*ip & 3) + { + SETFLOAT(&msg[*ip], 0); + (*ip)++; + } +} + +static void oscformat_list(t_oscformat *x, t_symbol *s, int argc, t_atom *argv) +{ + int typeindex = 0, j, msgindex, msgsize, datastart, ndata; + t_atom *msg; + char *sp, *formatp = x->x_format->s_name, typecode; + /* pass 1: go through args to find overall message size */ + for (j = ndata = 0, sp = formatp, msgindex = 0; j < argc;) + { + if (*sp) + typecode = *sp++; + else if (argv[j].a_type == A_SYMBOL) + typecode = 's'; + else typecode = 'f'; + if (typecode == 's') + msgindex += ROUNDUPTO4(strlen(argv[j].a_w.w_symbol->s_name) + 1); + else if (typecode == 'b') + { + int blobsize = 0x7fffffff, blobindex; + /* check if we have a nonnegative size field */ + if (argv[j].a_type == A_FLOAT && + (int)(argv[j].a_w.w_float) >= 0) + blobsize = (int)(argv[j].a_w.w_float); + if (blobsize > argc - j - 1) + blobsize = argc - j - 1; /* if no or bad size, eat it all */ + msgindex += 4 + ROUNDUPTO4(blobsize); + j += blobsize; + } + else msgindex += 4; + j++; + ndata++; + } + datastart = (int)(ROUNDUPTO4(strlen(x->x_pathbuf)+1) + ROUNDUPTO4(ndata + 2)); + msgsize = datastart + msgindex; + msg = (t_atom *)alloca(msgsize * sizeof(t_atom)); + putstring(msg, &typeindex, x->x_pathbuf); + SETFLOAT(&msg[typeindex], ','); + typeindex++; + /* pass 2: fill in types and data portion of packet */ + for (j = 0, sp = formatp, msgindex = datastart; j < argc;) + { + if (*sp) + typecode = *sp++; + else if (argv[j].a_type == A_SYMBOL) + typecode = 's'; + else typecode = 'f'; + SETFLOAT(&msg[typeindex], typecode & 0xff); + typeindex++; + if (typecode == 'f') + { + union + { + float z_f; + uint32_t z_i; + } z; + z.z_f = atom_getfloat(&argv[j]); + WRITEINT(msg+msgindex, z.z_i); + msgindex += 4; + } + else if (typecode == 'i') + { + int dat = atom_getfloat(&argv[j]); + WRITEINT(msg+msgindex, dat); + msgindex += 4; + } + else if (typecode == 's') + putstring(msg, &msgindex, argv[j].a_w.w_symbol->s_name); + else if (typecode == 'b') + { + int blobsize = 0x7fffffff, blobindex; + if (argv[j].a_type == A_FLOAT && + (int)(argv[j].a_w.w_float) >= 0) + blobsize = (int)(argv[j].a_w.w_float); + if (blobsize > argc - j - 1) + blobsize = argc - j - 1; + WRITEINT(msg+msgindex, blobsize); + msgindex += 4; + for (blobindex = 0; blobindex < blobsize; blobindex++) + SETFLOAT(msg+msgindex+blobindex, + (argv[j+1+blobindex].a_type == A_FLOAT ? + argv[j+1+blobindex].a_w.w_float : + (argv[j+1+blobindex].a_type == A_SYMBOL ? + argv[j+1+blobindex].a_w.w_symbol->s_name[0] & 0xff : + 0))); + j += blobsize; + while (blobsize & 3) + SETFLOAT(msg+msgindex+blobsize, 0), blobsize++; + msgindex += blobsize; + } + j++; + } + SETFLOAT(&msg[typeindex], 0); + typeindex++; + while (typeindex & 3) + SETFLOAT(&msg[typeindex], 0), typeindex++; + if (typeindex != datastart || msgindex != msgsize) + bug("oscformat: typeindex %d, datastart %d, msgindex %d, msgsize %d", + typeindex, datastart, msgindex, msgsize); + /* else post("datastart %d, msgsize %d", datastart, msgsize); */ + outlet_list(x->x_obj.ob_outlet, 0, msgsize, msg); +} + +static void oscformat_free(t_oscformat *x) +{ + freebytes(x->x_pathbuf, x->x_pathsize); +} + +static void *oscformat_new(t_symbol *s, int argc, t_atom *argv) +{ + t_oscformat *x = (t_oscformat *)pd_new(oscformat_class); + outlet_new(&x->x_obj, gensym("list")); + x->x_pathbuf = getbytes(1); + x->x_pathsize = 1; + *x->x_pathbuf = 0; + x->x_format = &s_; + if (argc > 1 && argv[0].a_type == A_SYMBOL && + argv[1].a_type == A_SYMBOL && + !strcmp(argv[0].a_w.w_symbol->s_name, "-f")) + { + oscformat_format(x, argv[1].a_w.w_symbol); + argc -= 2; + argv += 2; + } + oscformat_set(x, 0, argc, argv); + return (x); +} + +void oscformat_setup(void) +{ + oscformat_class = class_new(gensym("oscformat"), (t_newmethod)oscformat_new, + (t_method)oscformat_free, sizeof(t_oscformat), 0, A_GIMME, 0); + class_addmethod(oscformat_class, (t_method)oscformat_set, + gensym("set"), A_GIMME, 0); + class_addmethod(oscformat_class, (t_method)oscformat_format, + gensym("format"), A_DEFSYM, 0); + class_addlist(oscformat_class, oscformat_list); +} + + +/* ---------- fudiparse - parse bytelists to to FUDI messages ----------------- */ + +static t_class *fudiparse_class; + +typedef struct _fudiparse { + t_object x_obj; + t_outlet *x_msgout; + char *x_bytes; + size_t x_numbytes; +} t_fudiparse; + +static void fudiparse_binbufout(t_fudiparse *x, t_binbuf *b) +{ + int msg, natom = binbuf_getnatom(b); + t_atom *at = binbuf_getvec(b); + for (msg = 0; msg < natom;) { + int emsg; + for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA + && at[emsg].a_type != A_SEMI; emsg++) + ; + if (emsg > msg) { + int i; + /* check for illegal atoms */ + for (i = msg; i < emsg; i++) + if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM) { + pd_error(x, "fudiparse: got dollar sign in message"); + goto nodice; + } + + if (at[msg].a_type == A_FLOAT) { + if (emsg > msg + 1) + outlet_list(x->x_msgout, 0, emsg-msg, at + msg); + else outlet_float(x->x_msgout, at[msg].a_w.w_float); + } + else if (at[msg].a_type == A_SYMBOL) { + outlet_anything(x->x_msgout, at[msg].a_w.w_symbol, + emsg-msg-1, at + msg + 1); + } + } + nodice: + msg = emsg + 1; + } +} +static void fudiparse_list(t_fudiparse *x, t_symbol*s, int argc, t_atom*argv) { + size_t len = argc; + t_binbuf* bbuf = binbuf_new(); + char*cbuf; + if((size_t)argc > x->x_numbytes) { + freebytes(x->x_bytes, x->x_numbytes); + x->x_numbytes = argc; + x->x_bytes = getbytes(x->x_numbytes); + } + cbuf = x->x_bytes; + + while(argc--) { + char b = atom_getfloat(argv++); + *cbuf++ = b; + } + binbuf_text(bbuf, x->x_bytes, len); + + fudiparse_binbufout(x, bbuf); + + binbuf_free(bbuf); +} + +static void fudiparse_free(t_fudiparse *x) { + freebytes(x->x_bytes, x->x_numbytes); + x->x_bytes = NULL; + x->x_numbytes = 0; +} + +static void *fudiparse_new(void) { + t_fudiparse *x = (t_fudiparse *)pd_new(fudiparse_class); + x->x_msgout = outlet_new(&x->x_obj, 0); + x->x_numbytes = 1024; + x->x_bytes = getbytes(x->x_numbytes); + return (void *)x; +} + +void fudiparse_setup(void) { + fudiparse_class = class_new(gensym("fudiparse"), + (t_newmethod)fudiparse_new, + (t_method)fudiparse_free, + sizeof(t_fudiparse), CLASS_DEFAULT, + 0); + class_addlist(fudiparse_class, fudiparse_list); +} +/* --------- oscformat - format Pd (FUDI) messages to bytelists ------------ */ + +static t_class *fudiformat_class; + +typedef struct _fudiformat { + t_object x_obj; + t_outlet *x_msgout; + t_atom *x_atoms; + size_t x_numatoms; + int x_udp; +} t_fudiformat; + +static void fudiformat_any(t_fudiformat *x, t_symbol*s, int argc, t_atom*argv) { + char *buf; + int length; + int i; + t_atom at; + t_binbuf*bbuf = binbuf_new(); + SETSYMBOL(&at, s); + binbuf_add(bbuf, 1, &at); + + binbuf_add(bbuf, argc, argv); + + if(!x->x_udp) { + SETSEMI(&at); + binbuf_add(bbuf, 1, &at); + } + binbuf_gettext(bbuf, &buf, &length); + binbuf_free(bbuf); + + if((size_t)length>x->x_numatoms) { + freebytes(x->x_atoms, sizeof(*x->x_atoms) * x->x_numatoms); + x->x_numatoms = length; + x->x_atoms = getbytes(sizeof(*x->x_atoms) * x->x_numatoms); + } + + for(i=0; ix_atoms+i, buf[i]); + } + freebytes(buf, length); + outlet_list(x->x_msgout, 0, length, x->x_atoms); +} + +static void fudiformat_free(t_fudiformat *x) { + freebytes(x->x_atoms, sizeof(*x->x_atoms) * x->x_numatoms); + x->x_atoms = NULL; + x->x_numatoms = 0; +} + +static void *fudiformat_new(t_symbol*s) { + t_fudiformat *x = (t_fudiformat *)pd_new(fudiformat_class); + x->x_msgout = outlet_new(&x->x_obj, 0); + x->x_numatoms = 1024; + x->x_atoms = getbytes(sizeof(*x->x_atoms) * x->x_numatoms); + if (gensym("-u") == s) + x->x_udp = 1; + else if (gensym("-t") == s) + x->x_udp = 0; + else if (gensym("") != s) { + pd_error(x, "fudiformat: unsupported mode '%s'", s->s_name); + } + + return (void *)x; +} + +static void fudiformat_setup(void) { + fudiformat_class = class_new(gensym("fudiformat"), + (t_newmethod)fudiformat_new, + (t_method)fudiformat_free, + sizeof(t_fudiformat), CLASS_DEFAULT, + A_DEFSYMBOL, 0); + class_addanything(fudiformat_class, fudiformat_any); +} + + + +void x_misc_setup(void) +{ + random_setup(); + loadbang_setup(); + namecanvas_setup(); + cputime_setup(); + realtime_setup(); + oscparse_setup(); + oscformat_setup(); + fudiparse_setup(); + fudiformat_setup(); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/x_net.c b/ports/camomile/source/LibPd/pure-data/src/x_net.c new file mode 100644 index 00000000..5741fd12 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_net.c @@ -0,0 +1,644 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* network */ + +#include "m_pd.h" +#include "s_stuff.h" + +#include +#include +#ifdef _WIN32 +#include +#else +#include +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#endif + +#ifdef _WIN32 +# include /* MSVC or mingw on windows */ +#elif defined(__linux__) || defined(__APPLE__) +# include /* linux, mac, mingw, cygwin */ +#else +# include /* BSDs for example */ +#endif + +void socketreceiver_free(t_socketreceiver *x); + +static t_class *netsend_class; + +typedef struct _netsend +{ + t_object x_obj; + t_outlet *x_msgout; + t_outlet *x_connectout; + int x_sockfd; + int x_protocol; + int x_bin; + t_socketreceiver *x_receiver; +} t_netsend; + +static t_class *netreceive_class; + +typedef struct _netreceive +{ + t_netsend x_ns; + int x_nconnections; + int x_sockfd; + int *x_connections; + int x_old; + t_socketreceiver **x_receivers; +} t_netreceive; + +static void netreceive_notify(t_netreceive *x, int fd); + +static void *netsend_new(t_symbol *s, int argc, t_atom *argv) +{ + t_netsend *x = (t_netsend *)pd_new(netsend_class); + outlet_new(&x->x_obj, &s_float); + x->x_protocol = SOCK_STREAM; + x->x_bin = 0; + if (argc && argv->a_type == A_FLOAT) + { + x->x_protocol = (argv->a_w.w_float != 0 ? SOCK_DGRAM : SOCK_STREAM); + argc = 0; + } + else while (argc && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + if (!strcmp(argv->a_w.w_symbol->s_name, "-b")) + x->x_bin = 1; + else if (!strcmp(argv->a_w.w_symbol->s_name, "-u")) + x->x_protocol = SOCK_DGRAM; + else + { + pd_error(x, "netsend: unknown flag ..."); + postatom(argc, argv); endpost(); + } + argc--; argv++; + } + if (argc) + { + pd_error(x, "netsend: extra arguments ignored:"); + postatom(argc, argv); endpost(); + } + x->x_sockfd = -1; + x->x_receiver = NULL; + x->x_msgout = outlet_new(&x->x_obj, &s_anything); + return (x); +} + +static void netsend_readbin(t_netsend *x, int fd) +{ + unsigned char inbuf[MAXPDSTRING]; + int ret = (int)recv(fd, inbuf, MAXPDSTRING, 0), i; + if (!x->x_msgout) + { + bug("netsend_readbin"); + return; + } + if (ret <= 0) + { + if (ret < 0) + sys_sockerror("recv"); + sys_rmpollfn(fd); + sys_closesocket(fd); + if (x->x_obj.ob_pd == netreceive_class) + netreceive_notify((t_netreceive *)x, fd); + } + else if (x->x_protocol == SOCK_DGRAM) + { + t_atom *ap = (t_atom *)alloca(ret * sizeof(t_atom)); + for (i = 0; i < ret; i++) + SETFLOAT(ap+i, inbuf[i]); + outlet_list(x->x_msgout, 0, ret, ap); + } + else + { + for (i = 0; i < ret; i++) + outlet_float(x->x_msgout, inbuf[i]); + } +} + +static void netsend_doit(void *z, t_binbuf *b) +{ + t_atom messbuf[1024]; + t_netsend *x = (t_netsend *)z; + int msg, natom = binbuf_getnatom(b); + t_atom *at = binbuf_getvec(b); + for (msg = 0; msg < natom;) + { + int emsg; + for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA + && at[emsg].a_type != A_SEMI; emsg++) + ; + if (emsg > msg) + { + int i; + for (i = msg; i < emsg; i++) + if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM) + { + pd_error(x, "netreceive: got dollar sign in message"); + goto nodice; + } + if (at[msg].a_type == A_FLOAT) + { + if (emsg > msg + 1) + outlet_list(x->x_msgout, 0, emsg-msg, at + msg); + else outlet_float(x->x_msgout, at[msg].a_w.w_float); + } + else if (at[msg].a_type == A_SYMBOL) + outlet_anything(x->x_msgout, at[msg].a_w.w_symbol, + emsg-msg-1, at + msg + 1); + } + nodice: + msg = emsg + 1; + } +} + + +static void netsend_connect(t_netsend *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *hostname; + int fportno, sportno, sockfd, portno, srcportno, intarg; + struct sockaddr_in server = {0}; + struct sockaddr_in srcaddr = {0}; + struct hostent *hp; + /* check argument types */ + if ((argc < 2) || + argv[0].a_type != A_SYMBOL || + argv[1].a_type != A_FLOAT || + ((argc > 2) && argv[2].a_type != A_FLOAT)) + { + error("netsend_connect: bad arguments"); + return; + } + hostname = argv[0].a_w.w_symbol; + fportno = (int)argv[1].a_w.w_float; + sportno = (argc>2)?(int)argv[2].a_w.w_float:0; + portno = fportno; + srcportno = sportno; + if (x->x_sockfd >= 0) + { + error("netsend_connect: already connected"); + return; + } + + /* create a socket */ + sockfd = socket(AF_INET, x->x_protocol, 0); +#if 0 + fprintf(stderr, "send socket %d\n", sockfd); +#endif + if (sockfd < 0) + { + sys_sockerror("socket"); + return; + } + /* connect socket using hostname provided in command line */ + server.sin_family = AF_INET; + hp = gethostbyname(hostname->s_name); + if (hp == 0) + { + post("bad host?\n"); + sys_closesocket(sockfd); + return; + } +#if 0 + intarg = 0; + if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, + &intarg, sizeof(intarg)) < 0) + post("setsockopt (SO_RCVBUF) failed\n"); +#endif + intarg = 1; + if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, + (const void *)&intarg, sizeof(intarg)) < 0) + post("setting SO_BROADCAST"); + /* for stream (TCP) sockets, specify "nodelay" */ + if (x->x_protocol == SOCK_STREAM) + { + intarg = 1; + if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, + (char *)&intarg, sizeof(intarg)) < 0) + post("setsockopt (TCP_NODELAY) failed\n"); + } + memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); + + /* assign client port number */ + server.sin_port = htons((u_short)portno); + + + if (sportno != 0) { + post("connecting to dest port %d, src port %d", portno, sportno); + memset(&srcaddr, 0, sizeof(srcaddr)); + srcaddr.sin_family = AF_INET; + srcaddr.sin_addr.s_addr = htonl(INADDR_ANY); + srcaddr.sin_port = htons((u_short)sportno); + + if (bind (sockfd,(struct sockaddr *) &srcaddr, sizeof (srcaddr)) < 0) + { + sys_sockerror("setting source port"); + sys_closesocket(sockfd); + return; + } + } + else { + post("connecting to port %d", portno); + } + /* try to connect. LATER make a separate thread to do this + because it might block */ + if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) + { + sys_sockerror("connecting stream socket"); + sys_closesocket(sockfd); + return; + } + + x->x_sockfd = sockfd; + if (x->x_msgout) /* add polling function for return messages */ + { + if (x->x_bin) + sys_addpollfn(sockfd, (t_fdpollfn)netsend_readbin, x); + else + { + t_socketreceiver *y = + socketreceiver_new((void *)x, 0, netsend_doit, + x->x_protocol == SOCK_DGRAM); + sys_addpollfn(sockfd, (t_fdpollfn)socketreceiver_read, y); + x->x_receiver = y; + } + } + outlet_float(x->x_obj.ob_outlet, 1); +} + +static void netsend_disconnect(t_netsend *x) +{ + if (x->x_sockfd >= 0) + { + sys_rmpollfn(x->x_sockfd); + sys_closesocket(x->x_sockfd); + x->x_sockfd = -1; + if(x->x_receiver) + socketreceiver_free(x->x_receiver); + x->x_receiver=NULL; + outlet_float(x->x_obj.ob_outlet, 0); + } +} + +static int netsend_dosend(t_netsend *x, int sockfd, + t_symbol *s, int argc, t_atom *argv) +{ + char *buf, *bp; + int length, sent, fail = 0; + t_binbuf *b = 0; + if (x->x_bin) + { + int i; + buf = alloca(argc); + for (i = 0; i < argc; i++) + ((unsigned char *)buf)[i] = atom_getfloatarg(i, argc, argv); + length = argc; + } + else + { + t_atom at; + b = binbuf_new(); + binbuf_add(b, argc, argv); + SETSEMI(&at); + binbuf_add(b, 1, &at); + binbuf_gettext(b, &buf, &length); + } + for (bp = buf, sent = 0; sent < length;) + { + static double lastwarntime; + static double pleasewarn; + double timebefore = sys_getrealtime(); + int res = (int)send(sockfd, bp, length-sent, 0); + double timeafter = sys_getrealtime(); + int late = (timeafter - timebefore > 0.005); + if (late || pleasewarn) + { + if (timeafter > lastwarntime + 2) + { + post("netsend/netreceive blocked %d msec", + (int)(1000 * ((timeafter - timebefore) + + pleasewarn))); + pleasewarn = 0; + lastwarntime = timeafter; + } + else if (late) pleasewarn += timeafter - timebefore; + } + if (res <= 0) + { + sys_sockerror("netsend"); + fail = 1; + break; + } + else + { + sent += res; + bp += res; + } + } + done: + if (!x->x_bin) + { + t_freebytes(buf, length); + binbuf_free(b); + } + return (fail); +} + + +static void netsend_send(t_netsend *x, t_symbol *s, int argc, t_atom *argv) +{ + if (x->x_sockfd >= 0) + { + if (netsend_dosend(x, x->x_sockfd, s, argc, argv)) + netsend_disconnect(x); + } +} + +static void netsend_free(t_netsend *x) +{ + netsend_disconnect(x); +} + +static void netsend_setup(void) +{ + netsend_class = class_new(gensym("netsend"), (t_newmethod)netsend_new, + (t_method)netsend_free, + sizeof(t_netsend), 0, A_GIMME, 0); + class_addmethod(netsend_class, (t_method)netsend_connect, + gensym("connect"), A_GIMME, 0); + class_addmethod(netsend_class, (t_method)netsend_disconnect, + gensym("disconnect"), 0); + class_addmethod(netsend_class, (t_method)netsend_send, gensym("send"), + A_GIMME, 0); +} + +/* ----------------------------- netreceive ------------------------- */ +static void netreceive_notify(t_netreceive *x, int fd) +{ + int i; + for (i = 0; i < x->x_nconnections; i++) + { + if (x->x_connections[i] == fd) + { + memmove(x->x_connections+i, x->x_connections+(i+1), + sizeof(int) * (x->x_nconnections - (i+1))); + x->x_connections = (int *)t_resizebytes(x->x_connections, + x->x_nconnections * sizeof(int), + (x->x_nconnections-1) * sizeof(int)); + memmove(x->x_receivers+i, x->x_receivers+(i+1), + sizeof(t_socketreceiver*) * (x->x_nconnections - (i+1))); + + if(x->x_receivers[i]) + socketreceiver_free(x->x_receivers[i]); + x->x_receivers[i]=NULL; + x->x_receivers = (t_socketreceiver **)t_resizebytes(x->x_receivers, + x->x_nconnections * sizeof(t_socketreceiver*), + (x->x_nconnections-1) * sizeof(t_socketreceiver*)); + x->x_nconnections--; + } + } + outlet_float(x->x_ns.x_connectout, x->x_nconnections); +} + +static void netreceive_connectpoll(t_netreceive *x) +{ + int fd = accept(x->x_ns.x_sockfd, 0, 0); + if (fd < 0) post("netreceive: accept failed"); + else + { + int nconnections = x->x_nconnections+1; + + x->x_connections = (int *)t_resizebytes(x->x_connections, + x->x_nconnections * sizeof(int), nconnections * sizeof(int)); + x->x_connections[x->x_nconnections] = fd; + x->x_receivers = (t_socketreceiver **)t_resizebytes(x->x_receivers, + x->x_nconnections * sizeof(t_socketreceiver*), nconnections * sizeof(t_socketreceiver*)); + x->x_receivers[x->x_nconnections] = NULL; + if (x->x_ns.x_bin) + sys_addpollfn(fd, (t_fdpollfn)netsend_readbin, x); + else + { + t_socketreceiver *y = socketreceiver_new((void *)x, + (t_socketnotifier)netreceive_notify, + (x->x_ns.x_msgout ? netsend_doit : 0), 0); + sys_addpollfn(fd, (t_fdpollfn)socketreceiver_read, y); + x->x_receivers[x->x_nconnections] = y; + } + outlet_float(x->x_ns.x_connectout, (x->x_nconnections = nconnections)); + } +} + +static void netreceive_closeall(t_netreceive *x) +{ + int i; + for (i = 0; i < x->x_nconnections; i++) + { + sys_rmpollfn(x->x_connections[i]); + sys_closesocket(x->x_connections[i]); + if(x->x_receivers[i]) { + socketreceiver_free(x->x_receivers[i]); + x->x_receivers[i]=NULL; + } + } + x->x_connections = (int *)t_resizebytes(x->x_connections, + x->x_nconnections * sizeof(int), 0); + x->x_receivers = (t_socketreceiver**)t_resizebytes(x->x_receivers, + x->x_nconnections * sizeof(t_socketreceiver*), 0); + x->x_nconnections = 0; + if (x->x_ns.x_sockfd >= 0) + { + sys_rmpollfn(x->x_ns.x_sockfd); + sys_closesocket(x->x_ns.x_sockfd); + } + x->x_ns.x_sockfd = -1; + if(x->x_ns.x_receiver) + socketreceiver_free(x->x_ns.x_receiver); + x->x_ns.x_receiver=NULL; + if (x->x_ns.x_connectout) + outlet_float(x->x_ns.x_connectout, x->x_nconnections); +} + +static void netreceive_listen(t_netreceive *x, t_floatarg fportno) +{ + int portno = fportno, intarg; + struct sockaddr_in server = {0}; + netreceive_closeall(x); + if (portno <= 0) + return; + x->x_ns.x_sockfd = socket(AF_INET, x->x_ns.x_protocol, 0); + if (x->x_ns.x_sockfd < 0) + { + sys_sockerror("socket"); + return; + } +#if 0 + fprintf(stderr, "receive socket %d\n", x->x_ sockfd); +#endif + +#if 1 + /* ask OS to allow another Pd to repoen this port after we close it. */ + intarg = 1; + if (setsockopt(x->x_ns.x_sockfd, SOL_SOCKET, SO_REUSEADDR, + (char *)&intarg, sizeof(intarg)) < 0) + post("netreceive: setsockopt (SO_REUSEADDR) failed\n"); +#endif +#if 0 + intarg = 0; + if (setsockopt(x->x_ns.x_sockfd, SOL_SOCKET, SO_RCVBUF, + &intarg, sizeof(intarg)) < 0) + post("setsockopt (SO_RCVBUF) failed\n"); +#endif + intarg = 1; + if (setsockopt(x->x_ns.x_sockfd, SOL_SOCKET, SO_BROADCAST, + (const void *)&intarg, sizeof(intarg)) < 0) + post("netreceive: failed to sett SO_BROADCAST"); + /* Stream (TCP) sockets are set NODELAY */ + if (x->x_ns.x_protocol == SOCK_STREAM) + { + intarg = 1; + if (setsockopt(x->x_ns.x_sockfd, IPPROTO_TCP, TCP_NODELAY, + (char *)&intarg, sizeof(intarg)) < 0) + post("setsockopt (TCP_NODELAY) failed\n"); + } + /* assign server port number etc */ + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = htons((u_short)portno); + + /* name the socket */ + if (bind(x->x_ns.x_sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) + { + sys_sockerror("bind"); + sys_closesocket(x->x_ns.x_sockfd); + x->x_ns.x_sockfd = -1; + return; + } + + if (x->x_ns.x_protocol == SOCK_DGRAM) /* datagram protocol */ + { + if (x->x_ns.x_bin) + sys_addpollfn(x->x_ns.x_sockfd, (t_fdpollfn)netsend_readbin, x); + else + { + t_socketreceiver *y = socketreceiver_new((void *)x, + (t_socketnotifier)netreceive_notify, + (x->x_ns.x_msgout ? netsend_doit : 0), 1); + sys_addpollfn(x->x_ns.x_sockfd, (t_fdpollfn)socketreceiver_read, y); + x->x_ns.x_connectout = 0; + x->x_ns.x_receiver = y; + } + } + else /* streaming protocol */ + { + if (listen(x->x_ns.x_sockfd, 5) < 0) + { + sys_sockerror("listen"); + sys_closesocket(x->x_ns.x_sockfd); + x->x_ns.x_sockfd = -1; + } + else + { + sys_addpollfn(x->x_ns.x_sockfd, (t_fdpollfn)netreceive_connectpoll, x); + } + } +} + + +static void netreceive_send(t_netreceive *x, + t_symbol *s, int argc, t_atom *argv) +{ + int i; + for (i = 0; i < x->x_nconnections; i++) + { + if (netsend_dosend(&x->x_ns, x->x_connections[i], s, argc, argv)) + pd_error(x, "netreceive send message failed"); + /* should we now close the connection? */ + } +} + +static void *netreceive_new(t_symbol *s, int argc, t_atom *argv) +{ + t_netreceive *x = (t_netreceive *)pd_new(netreceive_class); + int portno = 0; + x->x_ns.x_protocol = SOCK_STREAM; + x->x_old = 0; + x->x_ns.x_bin = 0; + x->x_nconnections = 0; + x->x_connections = (int *)t_getbytes(0); + x->x_receivers = (t_socketreceiver **)t_getbytes(0); + x->x_ns.x_sockfd = -1; + if (argc && argv->a_type == A_FLOAT) + { + portno = atom_getfloatarg(0, argc, argv); + x->x_ns.x_protocol = (atom_getfloatarg(1, argc, argv) != 0 ? + SOCK_DGRAM : SOCK_STREAM); + x->x_old = (!strcmp(atom_getsymbolarg(2, argc, argv)->s_name, "old")); + argc = 0; + } + else + { + while (argc && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + if (!strcmp(argv->a_w.w_symbol->s_name, "-b")) + x->x_ns.x_bin = 1; + else if (!strcmp(argv->a_w.w_symbol->s_name, "-u")) + x->x_ns.x_protocol = SOCK_DGRAM; + else + { + pd_error(x, "netreceive: unknown flag ..."); + postatom(argc, argv); endpost(); + } + argc--; argv++; + } + } + if (argc && argv->a_type == A_FLOAT) + portno = argv->a_w.w_float, argc--, argv++; + if (argc) + { + pd_error(x, "netreceive: extra arguments ignored:"); + postatom(argc, argv); endpost(); + } + if (x->x_old) + { + /* old style, nonsecure version */ + x->x_ns.x_msgout = 0; + } + else x->x_ns.x_msgout = outlet_new(&x->x_ns.x_obj, &s_anything); + if (x->x_ns.x_protocol == SOCK_STREAM) + x->x_ns.x_connectout = outlet_new(&x->x_ns.x_obj, &s_float); + else + x->x_ns.x_connectout = 0; + /* create a socket */ + if (portno > 0) + netreceive_listen(x, portno); + + return (x); +} + +static void netreceive_setup(void) +{ + netreceive_class = class_new(gensym("netreceive"), + (t_newmethod)netreceive_new, (t_method)netreceive_closeall, + sizeof(t_netreceive), 0, A_GIMME, 0); + class_addmethod(netreceive_class, (t_method)netreceive_listen, + gensym("listen"), A_FLOAT, 0); + class_addmethod(netreceive_class, (t_method)netreceive_send, + gensym("send"), A_GIMME, 0); +} + +void x_net_setup(void) +{ + netsend_setup(); + netreceive_setup(); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/x_scalar.c b/ports/camomile/source/LibPd/pure-data/src/x_scalar.c new file mode 100644 index 00000000..cd5226d4 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_scalar.c @@ -0,0 +1,189 @@ +/* Copyright (c) 1997-2013 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* The "scalar" object. */ + +#include "m_pd.h" +#include "g_canvas.h" +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef _WIN32 +#include +#endif + +t_class *scalar_define_class; + +static void *scalar_define_new(t_symbol *s, int argc, t_atom *argv) +{ + t_atom a[9]; + t_glist *gl; + t_canvas *x, *z = canvas_getcurrent(); + t_symbol *templatesym = &s_float, *asym = gensym("#A"); + t_template *template; + t_scalar *sc; + int keep = 0; + while (argc && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + if (!strcmp(argv->a_w.w_symbol->s_name, "-k")) + keep = 1; + else + { + error("scalar define: unknown flag ..."); + postatom(argc, argv); + } + argc--; argv++; + } + if (argc && argv->a_type == A_SYMBOL) + { + templatesym = argv->a_w.w_symbol; + argc--; argv++; + } + if (argc) + { + post("warning: scalar define ignoring extra argument: "); + postatom(argc, argv); + } + + /* make a canvas... */ + SETFLOAT(a, 0); + SETFLOAT(a+1, 50); + SETFLOAT(a+2, 600); + SETFLOAT(a+3, 400); + SETSYMBOL(a+4, s); + SETFLOAT(a+5, 0); + x = canvas_new(0, 0, 6, a); + + x->gl_owner = z; + x->gl_private = 0; + /* put a scalar in it */ + template = template_findbyname(canvas_makebindsym(templatesym)); + if (!template) + { + pd_error(x, "scalar define: couldn't find template %s", + templatesym->s_name); + goto noscalar; + } + sc = scalar_new(x, canvas_makebindsym(templatesym)); + if (!sc) + { + pd_error(x, "%s: couldn't create scalar", templatesym->s_name); + goto noscalar; + } + sc->sc_gobj.g_next = 0; + x->gl_list = &sc->sc_gobj; + x->gl_private = keep; + /* bashily unbind #A -- this would create garbage if #A were + multiply bound but we believe in this context it's at most + bound to whichever text_define or array was created most recently */ + asym->s_thing = 0; + /* and now bind #A to us to receive following messages in the + saved file or copy buffer */ + pd_bind(&x->gl_obj.ob_pd, asym); +noscalar: + pd_this->pd_newest = &x->gl_pd; /* mimic action of canvas_pop() */ + pd_popsym(&x->gl_pd); + x->gl_loading = 0; + + /* bash the class to "scalar define" -- see comment in x_array,c */ + x->gl_obj.ob_pd = scalar_define_class; + return (x); +} + + /* send a pointer to the scalar to whomever is bound to the symbol */ +static void scalar_define_send(t_glist *x, t_symbol *s) +{ + if (!s->s_thing) + pd_error(x, "scalar_define_send: %s: no such object", s->s_name); + else if (x->gl_list && pd_class(&x->gl_list->g_pd) == scalar_class) + { + t_gpointer gp; + gpointer_init(&gp); + gpointer_setglist(&gp, x, (t_scalar *)&x->gl_list->g_pd); + pd_pointer(s->s_thing, &gp); + gpointer_unset(&gp); + } + else bug("scalar_define_send"); +} + + /* set to a list, used to restore from scalar_define_save()s below */ +static void scalar_define_set(t_glist *x, t_symbol *s, int argc, t_atom *argv) +{ + if (x->gl_list && pd_class(&x->gl_list->g_pd) == scalar_class) + { + t_binbuf *b = binbuf_new(); + int nextmsg = 0, natoms; + t_atom *vec; + glist_clear(x); + binbuf_restore(b, argc, argv); + natoms = binbuf_getnatom(b); + vec = binbuf_getvec(b); + canvas_readscalar(x, natoms, vec, &nextmsg, 0); + binbuf_free(b); + } + else bug("scalar_define_set"); +} + + /* save to a binbuf (for file save or copy) */ +static void scalar_define_save(t_gobj *z, t_binbuf *bb) +{ + t_glist *x = (t_glist *)z; + binbuf_addv(bb, "ssff", &s__X, gensym("obj"), + (float)x->gl_obj.te_xpix, (float)x->gl_obj.te_ypix); + binbuf_addbinbuf(bb, x->gl_obj.ob_binbuf); + binbuf_addsemi(bb); + if (x->gl_private && x->gl_list && + pd_class(&x->gl_list->g_pd) == scalar_class) + { + t_binbuf *b2 = binbuf_new(); + t_scalar *sc = (t_scalar *)(x->gl_list); + binbuf_addv(bb, "ss", gensym("#A"), gensym("set")); + canvas_writescalar(sc->sc_template, sc->sc_vec, b2, 0); + binbuf_addbinbuf(bb, b2); + binbuf_addsemi(bb); + binbuf_free(b2); + } +} + +/* overall creator for "scalar" objects - dispatch to "scalar define" etc */ +static void *scalarobj_new(t_symbol *s, int argc, t_atom *argv) +{ + if (!argc || argv[0].a_type != A_SYMBOL) + pd_this->pd_newest = scalar_define_new(s, argc, argv); + else + { + char *str = argv[0].a_w.w_symbol->s_name; + if (!strcmp(str, "d") || !strcmp(str, "define")) + pd_this->pd_newest = scalar_define_new(s, argc-1, argv+1); + else + { + error("scalar %s: unknown function", str); + pd_this->pd_newest = 0; + } + } + return (pd_this->pd_newest); +} + +void canvas_add_for_class(t_class *c); + +/* ---------------- global setup function -------------------- */ + +void x_scalar_setup(void ) +{ + scalar_define_class = class_new(gensym("scalar define"), 0, + (t_method)canvas_free, sizeof(t_canvas), 0, 0); + canvas_add_for_class(scalar_define_class); + class_addmethod(scalar_define_class, (t_method)scalar_define_send, + gensym("send"), A_SYMBOL, 0); + class_addmethod(scalar_define_class, (t_method)scalar_define_set, + gensym("set"), A_GIMME, 0); + class_sethelpsymbol(scalar_define_class, gensym("scalar-object")); + class_setsavefn(scalar_define_class, scalar_define_save); + + class_addcreator((t_newmethod)scalarobj_new, gensym("scalar"), A_GIMME, 0); + +} diff --git a/ports/camomile/source/LibPd/pure-data/src/x_text.c b/ports/camomile/source/LibPd/pure-data/src/x_text.c new file mode 100644 index 00000000..94a59475 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_text.c @@ -0,0 +1,2119 @@ +/* Copyright (c) 1997-1999 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* historically this file defined the qlist and textfile objects - at the +moment it also defines "text" but it may later be better to split this off. */ + +#include "m_pd.h" +#include "g_canvas.h" /* just for glist_getfont, bother */ +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef _WIN32 +#include +#endif +static t_class *text_define_class; + +#ifdef _WIN32 +# include /* MSVC or mingw on windows */ +#elif defined(__linux__) || defined(__APPLE__) +# include /* linux, mac, mingw, cygwin */ +#else +# include /* BSDs for example */ +#endif + +#ifndef HAVE_ALLOCA /* can work without alloca() but we never need it */ +#define HAVE_ALLOCA 1 +#endif +#define TEXT_NGETBYTE 100 /* bigger that this we use alloc, not alloca */ +#if HAVE_ALLOCA +#define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)((n) < TEXT_NGETBYTE ? \ + alloca((n) * sizeof(t_atom)) : getbytes((n) * sizeof(t_atom)))) +#define ATOMS_FREEA(x, n) ( \ + ((n) < TEXT_NGETBYTE || (freebytes((x), (n) * sizeof(t_atom)), 0))) +#else +#define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)getbytes((n) * sizeof(t_atom))) +#define ATOMS_FREEA(x, n) (freebytes((x), (n) * sizeof(t_atom))) +#endif + +/* --- common code for text define, textfile, and qlist for storing text -- */ + +typedef struct _textbuf +{ + t_object b_ob; + t_binbuf *b_binbuf; + t_canvas *b_canvas; + t_guiconnect *b_guiconnect; + t_symbol *b_sym; +} t_textbuf; + +static void textbuf_init(t_textbuf *x, t_symbol *sym) +{ + x->b_binbuf = binbuf_new(); + x->b_canvas = canvas_getcurrent(); + x->b_sym = sym; +} + +static void textbuf_senditup(t_textbuf *x) +{ + int i, ntxt; + char *txt; + if (!x->b_guiconnect) + return; + binbuf_gettext(x->b_binbuf, &txt, &ntxt); + sys_vgui("pdtk_textwindow_clear .x%lx\n", x); + for (i = 0; i < ntxt; ) + { + char *j = strchr(txt+i, '\n'); + if (!j) j = txt + ntxt; + sys_vgui("pdtk_textwindow_append .x%lx {%.*s\n}\n", + x, j-txt-i, txt+i); + i = (int)((j-txt)+1); + } + sys_vgui("pdtk_textwindow_setdirty .x%lx 0\n", x); + t_freebytes(txt, ntxt); +} + +static void textbuf_open(t_textbuf *x) +{ + if (x->b_guiconnect) + { + sys_vgui("wm deiconify .x%lx\n", x); + sys_vgui("raise .x%lx\n", x); + sys_vgui("focus .x%lx.text\n", x); + } + else + { + char buf[40]; + sys_vgui("pdtk_textwindow_open .x%lx %dx%d {%s} %d\n", + x, 600, 340, x->b_sym->s_name, + sys_hostfontsize(glist_getfont(x->b_canvas), + glist_getzoom(x->b_canvas))); + sprintf(buf, ".x%lx", (unsigned long)x); + x->b_guiconnect = guiconnect_new(&x->b_ob.ob_pd, gensym(buf)); + textbuf_senditup(x); + } +} + +static void textbuf_close(t_textbuf *x) +{ + sys_vgui("pdtk_textwindow_doclose .x%lx\n", x); + if (x->b_guiconnect) + { + guiconnect_notarget(x->b_guiconnect, 1000); + x->b_guiconnect = 0; + } +} + +static void textbuf_addline(t_textbuf *b, t_symbol *s, int argc, t_atom *argv) +{ + t_binbuf *z = binbuf_new(); + binbuf_restore(z, argc, argv); + binbuf_add(b->b_binbuf, binbuf_getnatom(z), binbuf_getvec(z)); + binbuf_free(z); +} + +static void textbuf_read(t_textbuf *x, t_symbol *s, int argc, t_atom *argv) +{ + int cr = 0; + t_symbol *filename; + while (argc && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + if (!strcmp(argv->a_w.w_symbol->s_name, "-c")) + cr = 1; + else + { + pd_error(x, "text read: unknown flag ..."); + postatom(argc, argv); endpost(); + } + argc--; argv++; + } + if (argc && argv->a_type == A_SYMBOL) + { + filename = argv->a_w.w_symbol; + argc--; argv++; + } + else + { + pd_error(x, "text read: no file name given"); + return; + } + if (argc) + { + post("warning: text define ignoring extra argument: "); + postatom(argc, argv); endpost(); + } + if (binbuf_read_via_canvas(x->b_binbuf, filename->s_name, x->b_canvas, cr)) + pd_error(x, "%s: read failed", filename->s_name); + textbuf_senditup(x); +} + +static void textbuf_write(t_textbuf *x, t_symbol *s, int argc, t_atom *argv) +{ + int cr = 0; + t_symbol *filename; + char buf[MAXPDSTRING]; + while (argc && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + if (!strcmp(argv->a_w.w_symbol->s_name, "-c")) + cr = 1; + else + { + pd_error(x, "text write: unknown flag ..."); + postatom(argc, argv); endpost(); + } + argc--; argv++; + } + if (argc && argv->a_type == A_SYMBOL) + { + filename = argv->a_w.w_symbol; + argc--; argv++; + } + else + { + pd_error(x, "text write: no file name given"); + return; + } + if (argc) + { + post("warning: text define ignoring extra argument: "); + postatom(argc, argv); endpost(); + } + canvas_makefilename(x->b_canvas, filename->s_name, + buf, MAXPDSTRING); + if (binbuf_write(x->b_binbuf, buf, "", cr)) + pd_error(x, "%s: write failed", filename->s_name); +} + +static void textbuf_free(t_textbuf *x) +{ + t_pd *x2; + binbuf_free(x->b_binbuf); + if (x->b_guiconnect) + { + sys_vgui("destroy .x%lx\n", x); + guiconnect_notarget(x->b_guiconnect, 1000); + } + /* just in case we're still bound to #A from loading... */ + while ((x2 = pd_findbyclass(gensym("#A"), text_define_class))) + pd_unbind(x2, gensym("#A")); +} + + /* random helper function */ +static int text_nthline(int n, t_atom *vec, int line, int *startp, int *endp) +{ + int i, cnt = 0; + for (i = 0; i < n; i++) + { + if (cnt == line) + { + int j = i, outc, k; + while (j < n && vec[j].a_type != A_SEMI && + vec[j].a_type != A_COMMA) + j++; + *startp = i; + *endp = j; + return (1); + } + else if (vec[i].a_type == A_SEMI || vec[i].a_type == A_COMMA) + cnt++; + } + return (0); +} + +/* text_define object - text buffer, accessible by other accessor objects */ + +typedef struct _text_define +{ + t_textbuf x_textbuf; + t_outlet *x_out; + t_outlet *x_notifyout; + t_symbol *x_bindsym; + t_scalar *x_scalar; /* faux scalar (struct text-scalar) to point to */ + t_gpointer x_gp; /* pointer to it */ + t_canvas *x_canvas; /* owning canvas whose stub we use for x_gp */ + unsigned char x_keep; /* whether to embed contents in patch on save */ +} t_text_define; + +#define x_ob x_textbuf.b_ob +#define x_binbuf x_textbuf.b_binbuf +#define x_canvas x_textbuf.b_canvas + +static void *text_define_new(t_symbol *s, int argc, t_atom *argv) +{ + t_text_define *x = (t_text_define *)pd_new(text_define_class); + t_symbol *asym = gensym("#A"); + x->x_keep = 0; + x->x_bindsym = &s_; + while (argc && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + if (!strcmp(argv->a_w.w_symbol->s_name, "-k")) + x->x_keep = 1; + else + { + pd_error(x, "text define: unknown flag ..."); + postatom(argc, argv); endpost(); + } + argc--; argv++; + } + if (argc && argv->a_type == A_SYMBOL) + { + pd_bind(&x->x_ob.ob_pd, argv->a_w.w_symbol); + x->x_bindsym = argv->a_w.w_symbol; + argc--; argv++; + } + if (argc) + { + post("warning: text define ignoring extra argument: "); + postatom(argc, argv); endpost(); + } + textbuf_init(&x->x_textbuf, *x->x_bindsym->s_name ? x->x_bindsym : + gensym("text")); + /* set up a scalar and a pointer to it that we can output */ + x->x_scalar = scalar_new(canvas_getcurrent(), gensym("pd-text")); + binbuf_free(x->x_scalar->sc_vec[2].w_binbuf); + x->x_scalar->sc_vec[2].w_binbuf = x->x_binbuf; + x->x_out = outlet_new(&x->x_ob, &s_pointer); + x->x_notifyout = outlet_new(&x->x_ob, 0); + gpointer_init(&x->x_gp); + x->x_canvas = canvas_getcurrent(); + /* bashily unbind #A -- this would create garbage if #A were + multiply bound but we believe in this context it's at most + bound to whichever text_define or array was created most recently */ + asym->s_thing = 0; + /* and now bind #A to us to receive following messages in the + saved file or copy buffer */ + pd_bind(&x->x_ob.ob_pd, asym); + return (x); +} + +static void text_define_clear(t_text_define *x) +{ + binbuf_clear(x->x_binbuf); + textbuf_senditup(&x->x_textbuf); +} + + /* from g_traversal.c - maybe put in a header? */ +t_binbuf *pointertobinbuf(t_pd *x, t_gpointer *gp, t_symbol *s, + const char *fname); + + /* these are unused; they copy text from this object to and from a text + field in a scalar. */ +static void text_define_frompointer(t_text_define *x, t_gpointer *gp, + t_symbol *s) +{ + t_binbuf *b = pointertobinbuf(&x->x_textbuf.b_ob.ob_pd, + gp, s, "text_frompointer"); + if (b) + { + t_gstub *gs = gp->gp_stub; + binbuf_clear(x->x_textbuf.b_binbuf); + binbuf_add(x->x_textbuf.b_binbuf, binbuf_getnatom(b), binbuf_getvec(b)); + } +} + +static void text_define_topointer(t_text_define *x, t_gpointer *gp, t_symbol *s) +{ + t_binbuf *b = pointertobinbuf(&x->x_textbuf.b_ob.ob_pd, + gp, s, "text_topointer"); + if (b) + { + t_gstub *gs = gp->gp_stub; + binbuf_clear(b); + binbuf_add(b, binbuf_getnatom(x->x_textbuf.b_binbuf), + binbuf_getvec(x->x_textbuf.b_binbuf)); + if (gs->gs_which == GP_GLIST) + scalar_redraw(gp->gp_un.gp_scalar, gs->gs_un.gs_glist); + else + { + t_array *owner_array = gs->gs_un.gs_array; + while (owner_array->a_gp.gp_stub->gs_which == GP_ARRAY) + owner_array = owner_array->a_gp.gp_stub->gs_un.gs_array; + scalar_redraw(owner_array->a_gp.gp_un.gp_scalar, + owner_array->a_gp.gp_stub->gs_un.gs_glist); + } + } +} + + /* bang: output a pointer to a struct containing this text */ +void text_define_bang(t_text_define *x) +{ + gpointer_setglist(&x->x_gp, x->x_canvas, x->x_scalar); + outlet_pointer(x->x_out, &x->x_gp); +} + + /* set from a list */ +void text_define_set(t_text_define *x, t_symbol *s, int argc, t_atom *argv) +{ + binbuf_restore(x->x_binbuf, argc, argv); + textbuf_senditup(&x->x_textbuf); +} + +static void text_define_save(t_gobj *z, t_binbuf *bb) +{ + t_text_define *x = (t_text_define *)z; + binbuf_addv(bb, "ssff", &s__X, gensym("obj"), + (float)x->x_ob.te_xpix, (float)x->x_ob.te_ypix); + binbuf_addbinbuf(bb, x->x_ob.ob_binbuf); + binbuf_addsemi(bb); + if (x->x_keep) + { + binbuf_addv(bb, "ss", gensym("#A"), gensym("set")); + binbuf_addbinbuf(bb, x->x_binbuf); + binbuf_addsemi(bb); + } + obj_saveformat(&x->x_ob, bb); +} + + /* notification from GUI that we've been updated */ +static void text_define_notify(t_text_define *x) +{ + outlet_anything(x->x_notifyout, gensym("updated"), 0, 0); + textbuf_senditup(&x->x_textbuf); +} + +static void text_define_free(t_text_define *x) +{ + textbuf_free(&x->x_textbuf); + if (x->x_bindsym != &s_) + pd_unbind(&x->x_ob.ob_pd, x->x_bindsym); + gpointer_unset(&x->x_gp); +} + +/* --- text_client - common code for objects that refer to text buffers -- */ + +typedef struct _text_client +{ + t_object tc_obj; + t_symbol *tc_sym; + t_gpointer tc_gp; + t_symbol *tc_struct; + t_symbol *tc_field; +} t_text_client; + + /* parse buffer-finding arguments */ +static void text_client_argparse(t_text_client *x, int *argcp, t_atom **argvp, + char *name) +{ + int argc = *argcp; + t_atom *argv = *argvp; + x->tc_sym = x->tc_struct = x->tc_field = 0; + gpointer_init(&x->tc_gp); + while (argc && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + if (!strcmp(argv->a_w.w_symbol->s_name, "-s") && + argc >= 3 && argv[1].a_type == A_SYMBOL && argv[2].a_type == A_SYMBOL) + { + x->tc_struct = canvas_makebindsym(argv[1].a_w.w_symbol); + x->tc_field = argv[2].a_w.w_symbol; + argc -= 2; argv += 2; + } + else + { + pd_error(x, "%s: unknown flag '%s'...", name, + argv->a_w.w_symbol->s_name); + } + argc--; argv++; + } + if (argc && argv->a_type == A_SYMBOL) + { + if (x->tc_struct) + pd_error(x, "%s: extra names after -s..", name); + else x->tc_sym = argv->a_w.w_symbol; + argc--; argv++; + } + *argcp = argc; + *argvp = argv; +} + + /* find the binbuf for this object. This should be reusable for other + objects. Prints an error message and returns 0 on failure. */ +static t_binbuf *text_client_getbuf(t_text_client *x) +{ + if (x->tc_sym) /* named text object */ + { + t_textbuf *y = (t_textbuf *)pd_findbyclass(x->tc_sym, + text_define_class); + if (y) + return (y->b_binbuf); + else + { + pd_error(x, "text: couldn't find text buffer '%s'", + x->tc_sym->s_name); + return (0); + } + } + else if (x->tc_struct) /* by pointer */ + { + t_template *template = template_findbyname(x->tc_struct); + t_gstub *gs = x->tc_gp.gp_stub; + t_word *vec; + int onset, type; + t_symbol *arraytype; + if (!template) + { + pd_error(x, "text: couldn't find struct %s", x->tc_struct->s_name); + return (0); + } + if (!gpointer_check(&x->tc_gp, 0)) + { + pd_error(x, "text: stale or empty pointer"); + return (0); + } + if (gs->gs_which == GP_ARRAY) + vec = x->tc_gp.gp_un.gp_w; + else vec = x->tc_gp.gp_un.gp_scalar->sc_vec; + + if (!template_find_field(template, + x->tc_field, &onset, &type, &arraytype)) + { + pd_error(x, "text: no field named %s", x->tc_field->s_name); + return (0); + } + if (type != DT_TEXT) + { + pd_error(x, "text: field %s not of type text", x->tc_field->s_name); + return (0); + } + return (*(t_binbuf **)(((char *)vec) + onset)); + } + else return (0); /* shouldn't happen */ +} + +static void text_client_senditup(t_text_client *x) +{ + if (x->tc_sym) /* named text object */ + { + t_textbuf *y = (t_textbuf *)pd_findbyclass(x->tc_sym, + text_define_class); + if (y) + textbuf_senditup(y); + else bug("text_client_senditup"); + } + else if (x->tc_struct) /* by pointer */ + { + t_template *template = template_findbyname(x->tc_struct); + t_gstub *gs = x->tc_gp.gp_stub; + if (!template) + { + pd_error(x, "text: couldn't find struct %s", x->tc_struct->s_name); + return; + } + if (!gpointer_check(&x->tc_gp, 0)) + { + pd_error(x, "text: stale or empty pointer"); + return; + } + if (gs->gs_which == GP_GLIST) + scalar_redraw(x->tc_gp.gp_un.gp_scalar, gs->gs_un.gs_glist); + else + { + t_array *owner_array = gs->gs_un.gs_array; + while (owner_array->a_gp.gp_stub->gs_which == GP_ARRAY) + owner_array = owner_array->a_gp.gp_stub->gs_un.gs_array; + scalar_redraw(owner_array->a_gp.gp_un.gp_scalar, + owner_array->a_gp.gp_stub->gs_un.gs_glist); + } + } +} + +static void text_client_free(t_text_client *x) +{ + gpointer_unset(&x->tc_gp); +} + +/* ------- text_get object - output all or part of nth lines ----------- */ +t_class *text_get_class; + +typedef struct _text_get +{ + t_text_client x_tc; + t_outlet *x_out1; /* list */ + t_outlet *x_out2; /* 1 if comma terminated, 0 if semi, 2 if none */ + t_float x_f1; /* field number, -1 for whole line */ + t_float x_f2; /* number of fields */ +} t_text_get; + +#define x_obj x_tc.tc_obj +#define x_sym x_tc.tc_sym +#define x_gp x_tc.tc_gp +#define x_struct x_tc.tc_struct +#define x_field x_tc.tc_field + +static void *text_get_new(t_symbol *s, int argc, t_atom *argv) +{ + t_text_get *x = (t_text_get *)pd_new(text_get_class); + x->x_out1 = outlet_new(&x->x_obj, &s_list); + x->x_out2 = outlet_new(&x->x_obj, &s_float); + floatinlet_new(&x->x_obj, &x->x_f1); + floatinlet_new(&x->x_obj, &x->x_f2); + x->x_f1 = -1; + x->x_f2 = 1; + text_client_argparse(&x->x_tc, &argc, &argv, "text get"); + if (argc) + { + if (argv->a_type == A_FLOAT) + x->x_f1 = argv->a_w.w_float; + else + { + post("text get: can't understand field number"); + postatom(argc, argv); endpost(); + } + argc--; argv++; + } + if (argc) + { + if (argv->a_type == A_FLOAT) + x->x_f2 = argv->a_w.w_float; + else + { + post("text get: can't understand field count"); + postatom(argc, argv); endpost(); + } + argc--; argv++; + } + if (argc) + { + post("warning: text get ignoring extra argument: "); + postatom(argc, argv); endpost(); + } + if (x->x_struct) + pointerinlet_new(&x->x_obj, &x->x_gp); + else symbolinlet_new(&x->x_obj, &x->x_tc.tc_sym); + return (x); +} + +static void text_get_float(t_text_get *x, t_floatarg f) +{ + t_binbuf *b = text_client_getbuf(&x->x_tc); + int start, end, n, startfield, nfield; + t_atom *vec; + if (!b) + return; + vec = binbuf_getvec(b); + n = binbuf_getnatom(b); + startfield = x->x_f1; + nfield = x->x_f2; + if (text_nthline(n, vec, f, &start, &end)) + { + int outc = end - start, k; + t_atom *outv; + if (x->x_f1 < 0) /* negative start field for whole line */ + { + /* tell us what terminated the line (semi or comma) */ + outlet_float(x->x_out2, (end < n && vec[end].a_type == A_COMMA)); + ATOMS_ALLOCA(outv, outc); + for (k = 0; k < outc; k++) + outv[k] = vec[start+k]; + outlet_list(x->x_out1, 0, outc, outv); + ATOMS_FREEA(outv, outc); + } + else if (startfield + nfield > outc) + pd_error(x, "text get: field request (%d %d) out of range", + startfield, nfield); + else + { + ATOMS_ALLOCA(outv, nfield); + for (k = 0; k < nfield; k++) + outv[k] = vec[(start+startfield)+k]; + outlet_list(x->x_out1, 0, nfield, outv); + ATOMS_FREEA(outv, nfield); + } + } + else if (x->x_f1 < 0) /* whole line but out of range: empty list and 2 */ + { + outlet_float(x->x_out2, 2); /* 2 for out of range */ + outlet_list(x->x_out1, 0, 0, 0); /* ... and empty list */ + } +} + +/* --------- text_set object - replace all or part of nth line ----------- */ +typedef struct _text_set +{ + t_text_client x_tc; + t_float x_f1; /* line number */ + t_float x_f2; /* field number, -1 for whole line */ +} t_text_set; + +t_class *text_set_class; + +static void *text_set_new(t_symbol *s, int argc, t_atom *argv) +{ + t_text_set *x = (t_text_set *)pd_new(text_set_class); + floatinlet_new(&x->x_obj, &x->x_f1); + floatinlet_new(&x->x_obj, &x->x_f2); + x->x_f1 = 0; + x->x_f2 = -1; + text_client_argparse(&x->x_tc, &argc, &argv, "text set"); + if (argc) + { + if (argv->a_type == A_FLOAT) + x->x_f1 = argv->a_w.w_float; + else + { + post("text set: can't understand line number"); + postatom(argc, argv); endpost(); + } + argc--; argv++; + } + if (argc) + { + if (argv->a_type == A_FLOAT) + x->x_f2 = argv->a_w.w_float; + else + { + post("text set: can't understand field number"); + postatom(argc, argv); endpost(); + } + argc--; argv++; + } + if (argc) + { + post("warning: text set ignoring extra argument: "); + postatom(argc, argv); endpost(); + } + if (x->x_struct) + pointerinlet_new(&x->x_obj, &x->x_gp); + else symbolinlet_new(&x->x_obj, &x->x_tc.tc_sym); + return (x); +} + +static void text_set_list(t_text_set *x, + t_symbol *s, int argc, t_atom *argv) +{ + t_binbuf *b = text_client_getbuf(&x->x_tc); + int start, end, n, fieldno = x->x_f2, i, + /* check for overflow in this conversion: */ + lineno = (x->x_f1 > (double)0x7fffffff ? 0x7fffffff : (int)x->x_f1); + t_atom *vec; + if (!b) + return; + vec = binbuf_getvec(b); + n = binbuf_getnatom(b); + if (lineno < 0) + { + pd_error(x, "text set: line number (%d) < 0", lineno); + return; + } + if (text_nthline(n, vec, lineno, &start, &end)) + { + if (fieldno < 0) + { + if (end - start != argc) /* grow or shrink */ + { + int oldn = n; + n = n + (argc - (end-start)); + if (n > oldn) + (void)binbuf_resize(b, n); + vec = binbuf_getvec(b); + memmove(&vec[start + argc], &vec[end], + sizeof(*vec) * (oldn - end)); + if (n < oldn) + { + (void)binbuf_resize(b, n); + vec = binbuf_getvec(b); + } + } + } + else + { + if (fieldno >= end - start) + { + pd_error(x, "text set: field number (%d) past end of line", + fieldno); + return; + } + if (fieldno + argc > end - start) + argc = (end - start) - fieldno; + start += fieldno; + } + } + else if (fieldno < 0) /* if line number too high just append to end */ + { + int addsemi = (n && vec[n-1].a_type != A_SEMI && + vec[n-1].a_type != A_COMMA), newsize = n + addsemi + argc + 1; + (void)binbuf_resize(b, newsize); + vec = binbuf_getvec(b); + if (addsemi) + SETSEMI(&vec[n]); + SETSEMI(&vec[newsize-1]); + start = n+addsemi; + } + else + { + post("text set: %d: line number out of range", lineno); + return; + } + for (i = 0; i < argc; i++) + { + if (argv[i].a_type == A_POINTER) + SETSYMBOL(&vec[start+i], gensym("(pointer)")); + else vec[start+i] = argv[i]; + } + text_client_senditup(&x->x_tc); +} + +/* --------- text_insert object - insert a line ----------- */ +typedef struct _text_insert +{ + t_text_client x_tc; + t_float x_f1; /* line number */ +} t_text_insert; + +t_class *text_insert_class; + +static void *text_insert_new(t_symbol *s, int argc, t_atom *argv) +{ + t_text_insert *x = (t_text_insert *)pd_new(text_insert_class); + floatinlet_new(&x->x_obj, &x->x_f1); + x->x_f1 = 0; + text_client_argparse(&x->x_tc, &argc, &argv, "text insert"); + if (argc) + { + if (argv->a_type == A_FLOAT) + x->x_f1 = argv->a_w.w_float; + else + { + post("text insert: can't understand line number"); + postatom(argc, argv); endpost(); + } + argc--; argv++; + } + if (argc) + { + post("warning: text insert ignoring extra argument: "); + postatom(argc, argv); endpost(); + } + if (x->x_struct) + pointerinlet_new(&x->x_obj, &x->x_gp); + else symbolinlet_new(&x->x_obj, &x->x_tc.tc_sym); + return (x); +} + +static void text_insert_list(t_text_insert *x, + t_symbol *s, int argc, t_atom *argv) +{ + t_binbuf *b = text_client_getbuf(&x->x_tc); + int start, end, n, nwas, i, + lineno = (x->x_f1 > (double)0x7fffffff ? 0x7fffffff : x->x_f1); + + t_atom *vec; + if (!b) + return; + if (lineno < 0) + { + pd_error(x, "text insert: line number (%d) < 0", lineno); + return; + } + nwas = binbuf_getnatom(b); + if (!text_nthline(nwas, binbuf_getvec(b), lineno, &start, &end)) + start = nwas; + (void)binbuf_resize(b, (n = nwas + argc + 1)); + vec = binbuf_getvec(b); + if (start < n) + memmove(&vec[start+(argc+1)], &vec[start], sizeof(*vec) * (nwas-start)); + for (i = 0; i < argc; i++) + { + if (argv[i].a_type == A_POINTER) + SETSYMBOL(&vec[start+i], gensym("(pointer)")); + else vec[start+i] = argv[i]; + } + SETSEMI(&vec[start+argc]); + text_client_senditup(&x->x_tc); +} + +/* --------- text_delete object - delete nth line ----------- */ +typedef struct _text_delete +{ + t_text_client x_tc; +} t_text_delete; + +t_class *text_delete_class; + +static void *text_delete_new(t_symbol *s, int argc, t_atom *argv) +{ + t_text_delete *x = (t_text_delete *)pd_new(text_delete_class); + text_client_argparse(&x->x_tc, &argc, &argv, "text delete"); + if (argc) + { + post("warning: text delete ignoring extra argument: "); + postatom(argc, argv); endpost(); + } + if (x->x_struct) + pointerinlet_new(&x->x_obj, &x->x_gp); + else symbolinlet_new(&x->x_obj, &x->x_tc.tc_sym); + return (x); +} + +static void text_delete_float(t_text_delete *x, t_floatarg f) +{ + t_binbuf *b = text_client_getbuf(&x->x_tc); + int start, end, n, + lineno = (f > (double)0x7fffffff ? 0x7fffffff : f); + t_atom *vec; + if (!b) + return; + vec = binbuf_getvec(b); + n = binbuf_getnatom(b); + if (lineno < 0) + binbuf_clear(b); + else if (text_nthline(n, vec, lineno, &start, &end)) + { + if (end < n) + end++; + memmove(&vec[start], &vec[end], sizeof(*vec) * (n - end)); + (void)binbuf_resize(b, n - (end - start)); + } + else + { + post("text delete: %d: line number out of range", lineno); + return; + } + text_client_senditup(&x->x_tc); +} + +/* ---------------- text_size object - output number of lines -------------- */ +t_class *text_size_class; + +typedef struct _text_size +{ + t_text_client x_tc; + t_outlet *x_out1; /* float */ +} t_text_size; + +static void *text_size_new(t_symbol *s, int argc, t_atom *argv) +{ + t_text_size *x = (t_text_size *)pd_new(text_size_class); + x->x_out1 = outlet_new(&x->x_obj, &s_float); + text_client_argparse(&x->x_tc, &argc, &argv, "text size"); + if (argc) + { + post("warning: text size ignoring extra argument: "); + postatom(argc, argv); endpost(); + } + if (x->x_struct) + pointerinlet_new(&x->x_obj, &x->x_gp); + else symbolinlet_new(&x->x_obj, &x->x_tc.tc_sym); + return (x); +} + +static void text_size_bang(t_text_size *x) +{ + t_binbuf *b = text_client_getbuf(&x->x_tc); + int n, i, cnt = 0; + t_atom *vec; + if (!b) + return; + vec = binbuf_getvec(b); + n = binbuf_getnatom(b); + for (i = 0; i < n; i++) + { + if (vec[i].a_type == A_SEMI || vec[i].a_type == A_COMMA) + cnt++; + } + if (n && vec[n-1].a_type != A_SEMI && vec[n-1].a_type != A_COMMA) + cnt++; + outlet_float(x->x_out1, cnt); +} + +static void text_size_float(t_text_size *x, t_floatarg f) +{ + t_binbuf *b = text_client_getbuf(&x->x_tc); + int start, end, n; + t_atom *vec; + if (!b) + return; + vec = binbuf_getvec(b); + n = binbuf_getnatom(b); + if (text_nthline(n, vec, f, &start, &end)) + outlet_float(x->x_out1, end-start); + else outlet_float(x->x_out1, -1); +} + +/* ---------------- text_tolist object - output text as a list ----------- */ +t_class *text_tolist_class; + +#define t_text_tolist t_text_client + +static void *text_tolist_new(t_symbol *s, int argc, t_atom *argv) +{ + t_text_tolist *x = (t_text_tolist *)pd_new(text_tolist_class); + outlet_new(&x->tc_obj, &s_list); + text_client_argparse(x, &argc, &argv, "text tolist"); + if (argc) + { + post("warning: text tolist ignoring extra argument: "); + postatom(argc, argv); endpost(); + } + if (x->tc_struct) + pointerinlet_new(&x->tc_obj, &x->tc_gp); + else symbolinlet_new(&x->tc_obj, &x->tc_sym); + return (x); +} + +static void text_tolist_bang(t_text_tolist *x) +{ + t_binbuf *b = text_client_getbuf(x), *b2; + int n, i, cnt = 0; + t_atom *vec; + if (!b) + return; + b2 = binbuf_new(); + binbuf_addbinbuf(b2, b); + outlet_list(x->tc_obj.ob_outlet, 0, binbuf_getnatom(b2), binbuf_getvec(b2)); + binbuf_free(b2); +} + +/* ------------- text_fromlist object - set text from a list -------- */ +t_class *text_fromlist_class; + +#define t_text_fromlist t_text_client + +static void *text_fromlist_new(t_symbol *s, int argc, t_atom *argv) +{ + t_text_fromlist *x = (t_text_fromlist *)pd_new(text_fromlist_class); + text_client_argparse(x, &argc, &argv, "text fromlist"); + if (argc) + { + post("warning: text fromlist ignoring extra argument: "); + postatom(argc, argv); endpost(); + } + if (x->tc_struct) + pointerinlet_new(&x->tc_obj, &x->tc_gp); + else symbolinlet_new(&x->tc_obj, &x->tc_sym); + return (x); +} + +static void text_fromlist_list(t_text_fromlist *x, + t_symbol *s, int argc, t_atom *argv) +{ + t_binbuf *b = text_client_getbuf(x); + if (!b) + return; + binbuf_clear(b); + binbuf_restore(b, argc, argv); + text_client_senditup(x); +} + +/* ---- text_search object - output index of line(s) matching criteria ---- */ + +t_class *text_search_class; + + /* relations we can test when searching: */ +#define KB_EQ 0 /* equal */ +#define KB_GT 1 /* > (etc..) */ +#define KB_GE 2 +#define KB_LT 3 +#define KB_LE 4 +#define KB_NEAR 5 /* anything matches but closer is better */ + +typedef struct _key +{ + int k_field; + int k_binop; +} t_key; + +typedef struct _text_search +{ + t_text_client x_tc; + t_outlet *x_out1; /* line indices */ + int x_nkeys; + t_key *x_keyvec; +} t_text_search; + +static void *text_search_new(t_symbol *s, int argc, t_atom *argv) +{ + t_text_search *x = (t_text_search *)pd_new(text_search_class); + int i, key, nkey, nextop; + x->x_out1 = outlet_new(&x->x_obj, &s_list); + text_client_argparse(&x->x_tc, &argc, &argv, "text search"); + for (i = nkey = 0; i < argc; i++) + if (argv[i].a_type == A_FLOAT) + nkey++; + if (nkey == 0) + nkey = 1; + x->x_nkeys = nkey; + x->x_keyvec = (t_key *)getbytes(nkey * sizeof(*x->x_keyvec)); + if (!argc) + x->x_keyvec[0].k_field = 0, x->x_keyvec[0].k_binop = KB_EQ; + else for (i = key = 0, nextop = -1; i < argc; i++) + { + if (argv[i].a_type == A_FLOAT) + { + x->x_keyvec[key].k_field = + (argv[i].a_w.w_float > 0 ? argv[i].a_w.w_float : 0); + x->x_keyvec[key].k_binop = (nextop >= 0 ? nextop : KB_EQ); + nextop = -1; + key++; + } + else + { + char *s = argv[i].a_w.w_symbol->s_name; + if (nextop >= 0) + pd_error(x, + "text search: extra operation argument ignored: %s", s); + else if (!strcmp(argv[i].a_w.w_symbol->s_name, ">")) + nextop = KB_GT; + else if (!strcmp(argv[i].a_w.w_symbol->s_name, ">=")) + nextop = KB_GE; + else if (!strcmp(argv[i].a_w.w_symbol->s_name, "<")) + nextop = KB_LT; + else if (!strcmp(argv[i].a_w.w_symbol->s_name, "<=")) + nextop = KB_LE; + else if (!strcmp(argv[i].a_w.w_symbol->s_name, "near")) + nextop = KB_NEAR; + else pd_error(x, + "text search: unknown operation argument: %s", s); + } + } + if (x->x_struct) + pointerinlet_new(&x->x_obj, &x->x_gp); + else symbolinlet_new(&x->x_obj, &x->x_tc.tc_sym); + return (x); +} + +static void text_search_list(t_text_search *x, + t_symbol *s, int argc, t_atom *argv) +{ + t_binbuf *b = text_client_getbuf(&x->x_tc); + int i, j, n, lineno, bestline = -1, beststart=-1, bestn, thisstart, thisn, + nkeys = x->x_nkeys, failed = 0; + t_atom *vec; + t_key *kp = x->x_keyvec; + if (!b) + return; + if (argc < nkeys) + { + pd_error(x, "need %d keys, only got %d in list", + nkeys, argc); + } + vec = binbuf_getvec(b); + n = binbuf_getnatom(b); + if (nkeys < 1) + bug("text_search"); + for (i = lineno = thisstart = 0; i < n; i++) + { + if (vec[i].a_type == A_SEMI || vec[i].a_type == A_COMMA || i == n-1) + { + int thisn = i - thisstart, j, field = x->x_keyvec[0].k_field, + binop = x->x_keyvec[0].k_binop; + /* do we match? */ + for (j = 0; j < argc; ) + { + if (field >= thisn || + vec[thisstart+field].a_type != argv[j].a_type) + goto nomatch; + if (argv[j].a_type == A_FLOAT) /* arg is a float */ + { + switch (binop) + { + case KB_EQ: + if (vec[thisstart+field].a_w.w_float != + argv[j].a_w.w_float) + goto nomatch; + break; + case KB_GT: + if (vec[thisstart+field].a_w.w_float <= + argv[j].a_w.w_float) + goto nomatch; + break; + case KB_GE: + if (vec[thisstart+field].a_w.w_float < + argv[j].a_w.w_float) + goto nomatch; + break; + case KB_LT: + if (vec[thisstart+field].a_w.w_float >= + argv[j].a_w.w_float) + goto nomatch; + break; + case KB_LE: + if (vec[thisstart+field].a_w.w_float > + argv[j].a_w.w_float) + goto nomatch; + break; + /* the other possibility ('near') never fails */ + } + } + else /* arg is a symbol */ + { + if (binop != KB_EQ) + { + if (!failed) + { + pd_error(x, + "text search (%s): only exact matches allowed for symbols", + argv[j].a_w.w_symbol->s_name); + failed = 1; + } + goto nomatch; + } + if (vec[thisstart+field].a_w.w_symbol != + argv[j].a_w.w_symbol) + goto nomatch; + } + if (++j >= nkeys) /* if at last key just increment field */ + field++; + else field = x->x_keyvec[j].k_field, /* else next key */ + binop = x->x_keyvec[j].k_binop; + } + /* the line matches. Now, if there is a previous match, are + we better than it? */ + if (bestline >= 0) + { + field = x->x_keyvec[0].k_field; + binop = x->x_keyvec[0].k_binop; + for (j = 0; j < argc; ) + { + if (field >= thisn + || vec[thisstart+field].a_type != argv[j].a_type) + bug("text search 2"); + if (argv[j].a_type == A_FLOAT) /* arg is a float */ + { + float thisv = vec[thisstart+field].a_w.w_float, + bestv = (beststart >= 0 ? + vec[beststart+field].a_w.w_float : -1e20); + switch (binop) + { + case KB_GT: + case KB_GE: + if (thisv < bestv) + goto replace; + else if (thisv > bestv) + goto nomatch; + break; + case KB_LT: + case KB_LE: + if (thisv > bestv) + goto replace; + else if (thisv < bestv) + goto nomatch; + break; + case KB_NEAR: + if (thisv >= argv[j].a_w.w_float && + bestv >= argv[j].a_w.w_float) + { + if (thisv < bestv) + goto replace; + else if (thisv > bestv) + goto nomatch; + } + else if (thisv <= argv[j].a_w.w_float && + bestv <= argv[j].a_w.w_float) + { + if (thisv > bestv) + goto replace; + else if (thisv < bestv) + goto nomatch; + } + else + { + float d1 = thisv - argv[j].a_w.w_float, + d2 = bestv - argv[j].a_w.w_float; + if (d1 < 0) + d1 = -d1; + if (d2 < 0) + d2 = -d2; + + if (d1 < d2) + goto replace; + else if (d1 > d2) + goto nomatch; + } + break; + /* the other possibility ('=') never decides */ + } + } + if (++j >= nkeys) /* last key - increment field */ + field++; + else field = x->x_keyvec[j].k_field, /* else next key */ + binop = x->x_keyvec[j].k_binop; + } + goto nomatch; /* a tie - keep the old one */ + replace: + bestline = lineno, beststart = thisstart, bestn = thisn; + } + /* no previous match so we're best */ + else bestline = lineno, beststart = thisstart, bestn = thisn; + nomatch: + lineno++; + thisstart = i+1; + } + } + outlet_float(x->x_out1, bestline); +} + +/* ---------------- text_sequence object - sequencer ----------- */ +t_class *text_sequence_class; + +typedef struct _text_sequence +{ + t_text_client x_tc; + t_outlet *x_mainout; /* outlet for lists, zero if "global" */ + t_outlet *x_waitout; /* outlet for wait times, zero if we never wait */ + t_outlet *x_endout; /* bang when hit end */ + int x_onset; + int x_argc; + t_atom *x_argv; + t_symbol *x_waitsym; /* symbol to initiate wait, zero if none */ + int x_waitargc; /* how many leading numbers to use for waiting */ + t_clock *x_clock; /* calback for auto mode */ + t_float x_nextdelay; + t_symbol *x_lastto; /* destination symbol if we're after a comma */ + unsigned char x_eaten; /* true if we've eaten leading numbers already */ + unsigned char x_loop; /* true if we can send multiple lines */ + unsigned char x_auto; /* set timer when we hit single-number time list */ +} t_text_sequence; + +static void text_sequence_tick(t_text_sequence *x); +static void text_sequence_tempo(t_text_sequence *x, + t_symbol *unitname, t_floatarg tempo); +void parsetimeunits(void *x, t_float amount, t_symbol *unitname, + t_float *unit, int *samps); /* time unit parsing from x_time.c */ + +static void *text_sequence_new(t_symbol *s, int argc, t_atom *argv) +{ + t_text_sequence *x = (t_text_sequence *)pd_new(text_sequence_class); + int global = 0; + text_client_argparse(&x->x_tc, &argc, &argv, "text sequence"); + x->x_waitsym = 0; + x->x_waitargc = 0; + x->x_eaten = 0; + x->x_loop = 0; + x->x_lastto = 0; + while (argc && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + if (!strcmp(argv->a_w.w_symbol->s_name, "-w") && argc >= 2) + { + if (argv[1].a_type == A_SYMBOL) + { + x->x_waitsym = argv[1].a_w.w_symbol; + x->x_waitargc = 0; + } + else + { + x->x_waitsym = 0; + if ((x->x_waitargc = argv[1].a_w.w_float) < 0) + x->x_waitargc = 0; + } + argc -= 1; argv += 1; + } + else if (!strcmp(argv->a_w.w_symbol->s_name, "-g")) + global = 1; + else if (!strcmp(argv->a_w.w_symbol->s_name, "-t") && argc >= 3) + { + text_sequence_tempo(x, atom_getsymbolarg(2, argc, argv), + atom_getfloatarg(1, argc, argv)); + argc -= 2; argv += 2; + } + else + { + pd_error(x, "text sequence: unknown flag '%s'...", + argv->a_w.w_symbol->s_name); + } + argc--; argv++; + } + if (argc) + { + post("warning: text sequence ignoring extra argument: "); + postatom(argc, argv); endpost(); + } + if (x->x_tc.tc_struct) + pointerinlet_new(&x->x_tc.tc_obj, &x->x_tc.tc_gp); + else symbolinlet_new(&x->x_tc.tc_obj, &x->x_tc.tc_sym); + x->x_argc = 0; + x->x_argv = (t_atom *)getbytes(0); + x->x_onset = 0x7fffffff; + x->x_mainout = (!global ? outlet_new(&x->x_obj, &s_list) : 0); + x->x_waitout = (global || x->x_waitsym || x->x_waitargc ? + outlet_new(&x->x_obj, &s_list) : 0); + x->x_endout = outlet_new(&x->x_obj, &s_bang); + x->x_clock = clock_new(x, (t_method)text_sequence_tick); + if (global) + { + if (x->x_waitargc) + pd_error(x, + "warning: text sequence: numeric 'w' argument ignored if '-g' given"); + x->x_waitargc = 0x40000000; + } + return (x); +} + +static void text_sequence_doit(t_text_sequence *x, int argc, t_atom *argv) +{ + t_binbuf *b = text_client_getbuf(&x->x_tc), *b2; + int n, i, onset, nfield, wait, eatsemi = 1, gotcomma = 0; + t_atom *vec, *outvec, *ap; + if (!b) + goto nosequence; + vec = binbuf_getvec(b); + n = binbuf_getnatom(b); + if (x->x_onset >= n) + { + nosequence: + x->x_onset = 0x7fffffff; + x->x_loop = x->x_auto = 0; + outlet_bang(x->x_endout); + return; + } + onset = x->x_onset; + + /* test if leading numbers, or a leading symbol equal to our + "wait symbol", are directing us to wait */ + if (!x->x_lastto && ( + (vec[onset].a_type == A_FLOAT && x->x_waitargc && !x->x_eaten) || + (vec[onset].a_type == A_SYMBOL && + vec[onset].a_w.w_symbol == x->x_waitsym))) + { + if (vec[onset].a_type == A_FLOAT) + { + for (i = onset; i < n && i < onset + x->x_waitargc && + vec[i].a_type == A_FLOAT; i++) + ; + x->x_eaten = 1; + eatsemi = 0; + } + else + { + for (i = onset; i < n && vec[i].a_type != A_SEMI && + vec[i].a_type != A_COMMA; i++) + ; + x->x_eaten = 1; + onset++; /* symbol isn't part of wait list */ + } + wait = 1; + } + else /* message to send */ + { + for (i = onset; i < n && vec[i].a_type != A_SEMI && + vec[i].a_type != A_COMMA; i++) + ; + wait = 0; + x->x_eaten = 0; + if (i < n && vec[i].a_type == A_COMMA) + gotcomma = 1; + } + nfield = i - onset; + i += eatsemi; + if (i >= n) + i = 0x7fffffff; + x->x_onset = i; + /* generate output list, realizing dolar sign atoms. Allocate one + extra atom in case we want to prepend a symbol later */ + ATOMS_ALLOCA(outvec, nfield+1); + for (i = 0, ap = vec+onset; i < nfield; i++, ap++) + { + int type = ap->a_type; + if (type == A_FLOAT || type == A_SYMBOL) + outvec[i] = *ap; + else if (type == A_DOLLAR) + { + int atno = ap->a_w.w_index-1; + if (atno < 0 || atno >= argc) + { + pd_error(x, "argument $%d out of range", atno+1); + SETFLOAT(outvec+i, 0); + } + else outvec[i] = argv[atno]; + } + else if (type == A_DOLLSYM) + { + t_symbol *s = + binbuf_realizedollsym(ap->a_w.w_symbol, argc, argv, 0); + if (s) + SETSYMBOL(outvec+i, s); + else + { + error("$%s: not enough arguments supplied", + ap->a_w.w_symbol->s_name); + SETSYMBOL(outvec+i, &s_symbol); + } + } + else bug("text sequence"); + } + if (wait) + { + x->x_loop = 0; + x->x_lastto = 0; + if (x->x_auto && nfield == 1 && outvec[0].a_type == A_FLOAT) + x->x_nextdelay = outvec[0].a_w.w_float; + else if (!x->x_waitout) + bug("text sequence 3"); + else + { + x->x_auto = 0; + outlet_list(x->x_waitout, 0, nfield, outvec); + } + } + else if (x->x_mainout) + { + int n2 = nfield; + if (x->x_lastto) + { + memmove(outvec+1, outvec, nfield * sizeof(*outvec)); + SETSYMBOL(outvec, x->x_lastto); + n2++; + } + if (!gotcomma) + x->x_lastto = 0; + else if (!x->x_lastto && nfield && outvec->a_type == A_SYMBOL) + x->x_lastto = outvec->a_w.w_symbol; + outlet_list(x->x_mainout, 0, n2, outvec); + } + else if (nfield) + { + t_symbol *tosym = x->x_lastto; + t_pd *to = 0; + t_atom *vecleft = outvec; + int nleft = nfield; + if (!tosym) + { + if (outvec[0].a_type != A_SYMBOL) + bug("text sequence 2"); + else tosym = outvec[0].a_w.w_symbol; + vecleft++; + nleft--; + } + if (tosym) + { + if (!(to = tosym->s_thing)) + pd_error(x, "%s: no such object", tosym->s_name); + } + x->x_lastto = (gotcomma ? tosym : 0); + if (to) + { + if (nleft > 0 && vecleft[0].a_type == A_SYMBOL) + typedmess(to, vecleft->a_w.w_symbol, nleft-1, vecleft+1); + else pd_list(to, 0, nleft, vecleft); + } + } + ATOMS_FREEA(outvec, nfield+1); +} + +static void text_sequence_list(t_text_sequence *x, t_symbol *s, int argc, + t_atom *argv) +{ + x->x_loop = 1; + while (x->x_loop) + { + if (argc) + text_sequence_doit(x, argc, argv); + else text_sequence_doit(x, x->x_argc, x->x_argv); + } +} + +static void text_sequence_stop(t_text_sequence *x) +{ + x->x_loop = 0; + if (x->x_auto) + { + clock_unset(x->x_clock); + x->x_auto = 0; + } +} + +static void text_sequence_tick(t_text_sequence *x) /* clock callback */ +{ + x->x_lastto = 0; + while (x->x_auto) + { + x->x_loop = 1; + while (x->x_loop) + text_sequence_doit(x, x->x_argc, x->x_argv); + if (x->x_nextdelay > 0) + break; + } + if (x->x_auto) + clock_delay(x->x_clock, x->x_nextdelay); +} + +static void text_sequence_auto(t_text_sequence *x) +{ + x->x_lastto = 0; + if (x->x_auto) + clock_unset(x->x_clock); + x->x_auto = 1; + text_sequence_tick(x); +} + +static void text_sequence_step(t_text_sequence *x) +{ + text_sequence_stop(x); + text_sequence_doit(x, x->x_argc, x->x_argv); +} + +static void text_sequence_line(t_text_sequence *x, t_floatarg f) +{ + t_binbuf *b = text_client_getbuf(&x->x_tc), *b2; + int n, start, end; + t_atom *vec; + if (!b) + return; + x->x_lastto = 0; + vec = binbuf_getvec(b); + n = binbuf_getnatom(b); + if (!text_nthline(n, vec, f, &start, &end)) + { + pd_error(x, "text sequence: line number %d out of range", (int)f); + x->x_onset = 0x7fffffff; + } + else x->x_onset = start; + x->x_eaten = 0; +} + +static void text_sequence_args(t_text_sequence *x, t_symbol *s, + int argc, t_atom *argv) +{ + int i; + x->x_argv = t_resizebytes(x->x_argv, + x->x_argc * sizeof(t_atom), argc * sizeof(t_atom)); + for (i = 0; i < argc; i++) + x->x_argv[i] = argv[i]; + x->x_argc = argc; +} + +static void text_sequence_tempo(t_text_sequence *x, + t_symbol *unitname, t_floatarg tempo) +{ + t_float unit; + int samps; + parsetimeunits(x, tempo, unitname, &unit, &samps); + clock_setunit(x->x_clock, unit, samps); +} + +static void text_sequence_free(t_text_sequence *x) +{ + t_freebytes(x->x_argv, sizeof(t_atom) * x->x_argc); + clock_free(x->x_clock); + text_client_free(&x->x_tc); +} + +/* --- overall creator for "text" objects: dispatch to "text define" etc --- */ +static void *text_new(t_symbol *s, int argc, t_atom *argv) +{ + if (!argc || argv[0].a_type != A_SYMBOL) + pd_this->pd_newest = text_define_new(s, argc, argv); + else + { + char *str = argv[0].a_w.w_symbol->s_name; + if (!strcmp(str, "d") || !strcmp(str, "define")) + pd_this->pd_newest = text_define_new(s, argc-1, argv+1); + else if (!strcmp(str, "get")) + pd_this->pd_newest = text_get_new(s, argc-1, argv+1); + else if (!strcmp(str, "set")) + pd_this->pd_newest = text_set_new(s, argc-1, argv+1); + else if (!strcmp(str, "insert")) + pd_this->pd_newest = text_insert_new(s, argc-1, argv+1); + else if (!strcmp(str, "delete")) + pd_this->pd_newest = text_delete_new(s, argc-1, argv+1); + else if (!strcmp(str, "size")) + pd_this->pd_newest = text_size_new(s, argc-1, argv+1); + else if (!strcmp(str, "tolist")) + pd_this->pd_newest = text_tolist_new(s, argc-1, argv+1); + else if (!strcmp(str, "fromlist")) + pd_this->pd_newest = text_fromlist_new(s, argc-1, argv+1); + else if (!strcmp(str, "search")) + pd_this->pd_newest = text_search_new(s, argc-1, argv+1); + else if (!strcmp(str, "sequence")) + pd_this->pd_newest = text_sequence_new(s, argc-1, argv+1); + else + { + error("list %s: unknown function", str); + pd_this->pd_newest = 0; + } + } + return (pd_this->pd_newest); +} + +/* the qlist and textfile objects, as of 0.44, are 'derived' from +* the text object above. Maybe later it will be desirable to add new +* functionality to textfile; qlist is an ancient holdover (1987) and +* is probably best left alone. +*/ + +typedef struct _qlist +{ + t_textbuf x_textbuf; + t_outlet *x_bangout; + int x_onset; /* playback position */ + t_clock *x_clock; + t_float x_tempo; + double x_whenclockset; + t_float x_clockdelay; + int x_rewound; /* we've been rewound since last start */ + int x_innext; /* we're currently inside the "next" routine */ +} t_qlist; +#define x_ob x_textbuf.b_ob +#define x_binbuf x_textbuf.b_binbuf +#define x_canvas x_textbuf.b_canvas + +static void qlist_tick(t_qlist *x); + +static t_class *qlist_class; + +static void *qlist_new( void) +{ + t_qlist *x = (t_qlist *)pd_new(qlist_class); + textbuf_init(&x->x_textbuf, gensym("qlist")); + x->x_clock = clock_new(x, (t_method)qlist_tick); + outlet_new(&x->x_ob, &s_list); + x->x_bangout = outlet_new(&x->x_ob, &s_bang); + x->x_onset = 0x7fffffff; + x->x_tempo = 1; + x->x_whenclockset = 0; + x->x_clockdelay = 0; + x->x_rewound = x->x_innext = 0; + return (x); +} + +static void qlist_rewind(t_qlist *x) +{ + x->x_onset = 0; + if (x->x_clock) clock_unset(x->x_clock); + x->x_whenclockset = 0; + x->x_rewound = 1; +} + +static void qlist_donext(t_qlist *x, int drop, int automatic) +{ + t_pd *target = 0; + if (x->x_innext) + { + pd_error(x, "qlist sent 'next' from within itself"); + return; + } + x->x_innext = 1; + while (1) + { + int argc = binbuf_getnatom(x->x_binbuf), + count, onset = x->x_onset, onset2, wasrewound; + t_atom *argv = binbuf_getvec(x->x_binbuf); + t_atom *ap = argv + onset, *ap2; + if (onset >= argc) goto end; + while (ap->a_type == A_SEMI || ap->a_type == A_COMMA) + { + if (ap->a_type == A_SEMI) target = 0; + onset++, ap++; + if (onset >= argc) goto end; + } + + if (!target && ap->a_type == A_FLOAT) + { + ap2 = ap + 1; + onset2 = onset + 1; + while (onset2 < argc && ap2->a_type == A_FLOAT) + onset2++, ap2++; + x->x_onset = onset2; + if (automatic) + { + clock_delay(x->x_clock, + x->x_clockdelay = ap->a_w.w_float * x->x_tempo); + x->x_whenclockset = clock_getsystime(); + } + else outlet_list(x->x_ob.ob_outlet, 0, onset2-onset, ap); + x->x_innext = 0; + return; + } + ap2 = ap + 1; + onset2 = onset + 1; + while (onset2 < argc && + (ap2->a_type == A_FLOAT || ap2->a_type == A_SYMBOL)) + onset2++, ap2++; + x->x_onset = onset2; + count = onset2 - onset; + if (!target) + { + if (ap->a_type != A_SYMBOL) continue; + else if (!(target = ap->a_w.w_symbol->s_thing)) + { + pd_error(x, "qlist: %s: no such object", + ap->a_w.w_symbol->s_name); + continue; + } + ap++; + onset++; + count--; + if (!count) + { + x->x_onset = onset2; + continue; + } + } + wasrewound = x->x_rewound; + x->x_rewound = 0; + if (!drop) + { + if (ap->a_type == A_FLOAT) + typedmess(target, &s_list, count, ap); + else if (ap->a_type == A_SYMBOL) + typedmess(target, ap->a_w.w_symbol, count-1, ap+1); + } + if (x->x_rewound) + { + x->x_innext = 0; + return; + } + x->x_rewound = wasrewound; + } /* while (1); never falls through */ + +end: + x->x_onset = 0x7fffffff; + x->x_whenclockset = 0; + x->x_innext = 0; + outlet_bang(x->x_bangout); +} + +static void qlist_next(t_qlist *x, t_floatarg drop) +{ + qlist_donext(x, drop != 0, 0); +} + +static void qlist_bang(t_qlist *x) +{ + qlist_rewind(x); + /* if we're restarted reentrantly from a "next" message set ourselves + up to do this non-reentrantly after a delay of 0 */ + if (x->x_innext) + { + x->x_whenclockset = clock_getsystime(); + x->x_clockdelay = 0; + clock_delay(x->x_clock, 0); + } + else qlist_donext(x, 0, 1); +} + +static void qlist_tick(t_qlist *x) +{ + x->x_whenclockset = 0; + qlist_donext(x, 0, 1); +} + +static void qlist_add(t_qlist *x, t_symbol *s, int argc, t_atom *argv) +{ + t_atom a; + SETSEMI(&a); + binbuf_add(x->x_binbuf, argc, argv); + binbuf_add(x->x_binbuf, 1, &a); +} + +static void qlist_add2(t_qlist *x, t_symbol *s, int argc, t_atom *argv) +{ + binbuf_add(x->x_binbuf, argc, argv); +} + +static void qlist_clear(t_qlist *x) +{ + qlist_rewind(x); + binbuf_clear(x->x_binbuf); +} + +static void qlist_set(t_qlist *x, t_symbol *s, int argc, t_atom *argv) +{ + qlist_clear(x); + qlist_add(x, s, argc, argv); +} + +static void qlist_read(t_qlist *x, t_symbol *filename, t_symbol *format) +{ + int cr = 0; + if (!strcmp(format->s_name, "cr")) + cr = 1; + else if (*format->s_name) + pd_error(x, "qlist_read: unknown flag: %s", format->s_name); + + if (binbuf_read_via_canvas(x->x_binbuf, filename->s_name, x->x_canvas, cr)) + pd_error(x, "%s: read failed", filename->s_name); + x->x_onset = 0x7fffffff; + x->x_rewound = 1; +} + +static void qlist_write(t_qlist *x, t_symbol *filename, t_symbol *format) +{ + int cr = 0; + char buf[MAXPDSTRING]; + canvas_makefilename(x->x_canvas, filename->s_name, + buf, MAXPDSTRING); + if (!strcmp(format->s_name, "cr")) + cr = 1; + else if (*format->s_name) + pd_error(x, "qlist_read: unknown flag: %s", format->s_name); + if (binbuf_write(x->x_binbuf, buf, "", cr)) + pd_error(x, "%s: write failed", filename->s_name); +} + +static void qlist_print(t_qlist *x) +{ + post("--------- textfile or qlist contents: -----------"); + binbuf_print(x->x_binbuf); +} + +static void qlist_tempo(t_qlist *x, t_float f) +{ + t_float newtempo; + if (f < 1e-20) f = 1e-20; + else if (f > 1e20) f = 1e20; + newtempo = 1./f; + if (x->x_whenclockset != 0) + { + t_float elapsed = clock_gettimesince(x->x_whenclockset); + t_float left = x->x_clockdelay - elapsed; + if (left < 0) left = 0; + left *= newtempo / x->x_tempo; + clock_delay(x->x_clock, left); + } + x->x_tempo = newtempo; +} + +static void qlist_free(t_qlist *x) +{ + textbuf_free(&x->x_textbuf); + clock_free(x->x_clock); +} + +/* -------------------- textfile ------------------------------- */ + +/* has the same struct as qlist (so we can reuse some of its +* methods) but "sequencing" here only relies on 'binbuf' and 'onset' +* fields. +*/ + +static t_class *textfile_class; + +static void *textfile_new( void) +{ + t_qlist *x = (t_qlist *)pd_new(textfile_class); + textbuf_init(&x->x_textbuf, gensym("textfile")); + outlet_new(&x->x_ob, &s_list); + x->x_bangout = outlet_new(&x->x_ob, &s_bang); + x->x_onset = 0x7fffffff; + x->x_rewound = 0; + x->x_tempo = 1; + x->x_whenclockset = 0; + x->x_clockdelay = 0; + x->x_clock = NULL; + return (x); +} + +static void textfile_bang(t_qlist *x) +{ + int argc = binbuf_getnatom(x->x_binbuf), + count, onset = x->x_onset, onset2; + t_atom *argv = binbuf_getvec(x->x_binbuf); + t_atom *ap = argv + onset, *ap2; + while (onset < argc && + (ap->a_type == A_SEMI || ap->a_type == A_COMMA)) + onset++, ap++; + onset2 = onset; + ap2 = ap; + while (onset2 < argc && + (ap2->a_type != A_SEMI && ap2->a_type != A_COMMA)) + onset2++, ap2++; + if (onset2 > onset) + { + x->x_onset = onset2; + if (ap->a_type == A_SYMBOL) + outlet_anything(x->x_ob.ob_outlet, ap->a_w.w_symbol, + onset2-onset-1, ap+1); + else outlet_list(x->x_ob.ob_outlet, 0, onset2-onset, ap); + } + else + { + x->x_onset = 0x7fffffff; + outlet_bang(x->x_bangout); + } +} + +static void textfile_rewind(t_qlist *x) +{ + x->x_onset = 0; +} + +/* ---------------- global setup function -------------------- */ + +static t_pd *text_templatecanvas; +static char text_templatefile[] = "\ +canvas 0 0 458 153 10;\n\ +#X obj 43 31 struct text float x float y text t;\n\ +"; + +/* create invisible, built-in canvas to supply template containing one text +field named 't'. I don't know how to make this not break +pre-0.45 patches using templates named 'text'... perhaps this is a minor +enough incompatibility that I'll just get away with it. */ + +void text_template_init( void) +{ + t_binbuf *b; + b = binbuf_new(); + + glob_setfilename(0, gensym("_text_template"), gensym(".")); + binbuf_text(b, text_templatefile, strlen(text_templatefile)); + binbuf_eval(b, &pd_canvasmaker, 0, 0); + vmess(s__X.s_thing, gensym("pop"), "i", 0); + + glob_setfilename(0, &s_, &s_); + binbuf_free(b); +} + +void x_qlist_setup(void ) +{ + text_template_init(); + text_define_class = class_new(gensym("text define"), + (t_newmethod)text_define_new, + (t_method)text_define_free, sizeof(t_text_define), 0, A_GIMME, 0); + class_addmethod(text_define_class, (t_method)textbuf_open, + gensym("click"), 0); + class_addmethod(text_define_class, (t_method)textbuf_close, + gensym("close"), 0); + class_addmethod(text_define_class, (t_method)textbuf_addline, + gensym("addline"), A_GIMME, 0); + class_addmethod(text_define_class, (t_method)text_define_notify, + gensym("notify"), 0, 0); + class_addmethod(text_define_class, (t_method)text_define_set, + gensym("set"), A_GIMME, 0); + class_addmethod(text_define_class, (t_method)text_define_clear, + gensym("clear"), 0); + class_addmethod(text_define_class, (t_method)textbuf_write, + gensym("write"), A_GIMME, 0); + class_addmethod(text_define_class, (t_method)textbuf_read, + gensym("read"), A_GIMME, 0); + class_setsavefn(text_define_class, text_define_save); + class_addbang(text_define_class, text_define_bang); + class_sethelpsymbol(text_define_class, gensym("text-object")); + + class_addcreator((t_newmethod)text_new, gensym("text"), A_GIMME, 0); + + text_get_class = class_new(gensym("text get"), + (t_newmethod)text_get_new, (t_method)text_client_free, + sizeof(t_text_get), 0, A_GIMME, 0); + class_addfloat(text_get_class, text_get_float); + class_sethelpsymbol(text_get_class, gensym("text-object")); + + text_set_class = class_new(gensym("text set"), + (t_newmethod)text_set_new, (t_method)text_client_free, + sizeof(t_text_set), 0, A_GIMME, 0); + class_addlist(text_set_class, text_set_list); + class_sethelpsymbol(text_set_class, gensym("text-object")); + + text_insert_class = class_new(gensym("text insert"), + (t_newmethod)text_insert_new, (t_method)text_client_free, + sizeof(t_text_insert), 0, A_GIMME, 0); + class_addlist(text_insert_class, text_insert_list); + class_sethelpsymbol(text_insert_class, gensym("text-object")); + + text_delete_class = class_new(gensym("text delete"), + (t_newmethod)text_delete_new, (t_method)text_client_free, + sizeof(t_text_delete), 0, A_GIMME, 0); + class_addfloat(text_delete_class, text_delete_float); + class_sethelpsymbol(text_delete_class, gensym("text-object")); + + text_size_class = class_new(gensym("text size"), + (t_newmethod)text_size_new, (t_method)text_client_free, + sizeof(t_text_size), 0, A_GIMME, 0); + class_addbang(text_size_class, text_size_bang); + class_addfloat(text_size_class, text_size_float); + class_sethelpsymbol(text_size_class, gensym("text-object")); + + text_tolist_class = class_new(gensym("text tolist"), + (t_newmethod)text_tolist_new, (t_method)text_client_free, + sizeof(t_text_tolist), 0, A_GIMME, 0); + class_addbang(text_tolist_class, text_tolist_bang); + class_sethelpsymbol(text_tolist_class, gensym("text-object")); + + text_fromlist_class = class_new(gensym("text fromlist"), + (t_newmethod)text_fromlist_new, (t_method)text_client_free, + sizeof(t_text_fromlist), 0, A_GIMME, 0); + class_addlist(text_fromlist_class, text_fromlist_list); + class_sethelpsymbol(text_fromlist_class, gensym("text-object")); + + text_search_class = class_new(gensym("text search"), + (t_newmethod)text_search_new, (t_method)text_client_free, + sizeof(t_text_search), 0, A_GIMME, 0); + class_addlist(text_search_class, text_search_list); + class_sethelpsymbol(text_search_class, gensym("text-object")); + + text_sequence_class = class_new(gensym("text sequence"), + (t_newmethod)text_sequence_new, (t_method)text_sequence_free, + sizeof(t_text_sequence), 0, A_GIMME, 0); + class_addmethod(text_sequence_class, (t_method)text_sequence_step, + gensym("step"), 0); + class_addmethod(text_sequence_class, (t_method)text_sequence_line, + gensym("line"), A_FLOAT, 0); + class_addmethod(text_sequence_class, (t_method)text_sequence_auto, + gensym("auto"), 0); + class_addmethod(text_sequence_class, (t_method)text_sequence_stop, + gensym("stop"), 0); + class_addmethod(text_sequence_class, (t_method)text_sequence_args, + gensym("args"), A_GIMME, 0); + class_addmethod(text_sequence_class, (t_method)text_sequence_tempo, + gensym("tempo"), A_FLOAT, A_SYMBOL, 0); + class_addlist(text_sequence_class, text_sequence_list); + class_sethelpsymbol(text_sequence_class, gensym("text-object")); + + qlist_class = class_new(gensym("qlist"), (t_newmethod)qlist_new, + (t_method)qlist_free, sizeof(t_qlist), 0, 0); + class_addmethod(qlist_class, (t_method)qlist_rewind, gensym("rewind"), 0); + class_addmethod(qlist_class, (t_method)qlist_next, + gensym("next"), A_DEFFLOAT, 0); + class_addmethod(qlist_class, (t_method)qlist_set, gensym("set"), + A_GIMME, 0); + class_addmethod(qlist_class, (t_method)qlist_clear, gensym("clear"), 0); + class_addmethod(qlist_class, (t_method)qlist_add, gensym("add"), + A_GIMME, 0); + class_addmethod(qlist_class, (t_method)qlist_add2, gensym("add2"), + A_GIMME, 0); + class_addmethod(qlist_class, (t_method)qlist_add, gensym("append"), + A_GIMME, 0); + class_addmethod(qlist_class, (t_method)qlist_read, gensym("read"), + A_SYMBOL, A_DEFSYM, 0); + class_addmethod(qlist_class, (t_method)qlist_write, gensym("write"), + A_SYMBOL, A_DEFSYM, 0); + class_addmethod(qlist_class, (t_method)textbuf_open, gensym("click"), 0); + class_addmethod(qlist_class, (t_method)textbuf_close, gensym("close"), 0); + class_addmethod(qlist_class, (t_method)textbuf_addline, + gensym("addline"), A_GIMME, 0); + class_addmethod(qlist_class, (t_method)textbuf_senditup, + gensym("notify"), 0, 0); + class_addmethod(qlist_class, (t_method)qlist_print, gensym("print"), + A_DEFSYM, 0); + class_addmethod(qlist_class, (t_method)qlist_tempo, + gensym("tempo"), A_FLOAT, 0); + class_addbang(qlist_class, qlist_bang); + + textfile_class = class_new(gensym("textfile"), (t_newmethod)textfile_new, + (t_method)textbuf_free, sizeof(t_qlist), 0, 0); + class_addmethod(textfile_class, (t_method)textfile_rewind, gensym("rewind"), + 0); + class_addmethod(textfile_class, (t_method)qlist_set, gensym("set"), + A_GIMME, 0); + class_addmethod(textfile_class, (t_method)qlist_clear, gensym("clear"), 0); + class_addmethod(textfile_class, (t_method)qlist_add, gensym("add"), + A_GIMME, 0); + class_addmethod(textfile_class, (t_method)qlist_add2, gensym("add2"), + A_GIMME, 0); + class_addmethod(textfile_class, (t_method)qlist_add, gensym("append"), + A_GIMME, 0); + class_addmethod(textfile_class, (t_method)qlist_read, gensym("read"), + A_SYMBOL, A_DEFSYM, 0); + class_addmethod(textfile_class, (t_method)qlist_write, gensym("write"), + A_SYMBOL, A_DEFSYM, 0); + class_addmethod(textfile_class, (t_method)textbuf_open, gensym("click"), 0); + class_addmethod(textfile_class, (t_method)textbuf_close, gensym("close"), + 0); + class_addmethod(textfile_class, (t_method)textbuf_addline, + gensym("addline"), A_GIMME, 0); + class_addmethod(textfile_class, (t_method)textbuf_senditup, + gensym("notify"), 0, 0); + class_addmethod(textfile_class, (t_method)qlist_print, gensym("print"), + A_DEFSYM, 0); + class_addbang(textfile_class, textfile_bang); +} + diff --git a/ports/camomile/source/LibPd/pure-data/src/x_time.c b/ports/camomile/source/LibPd/pure-data/src/x_time.c new file mode 100644 index 00000000..fffe12e4 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_time.c @@ -0,0 +1,653 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* clock objects */ + +#include "m_pd.h" +#include +#include + + /* parse a time unit such as "5 msec", "60 perminute", or "1 sample" to + a form usable by clock_setunit)( and clock_gettimesincewithunits(). + This brute-force search through symbols really ought not to be done on + the fly for incoming 'tempo' messages, hmm... This isn't public because + its interface migth want to change - but it's used in x_text.c as well + as here. */ +void parsetimeunits(void *x, t_float amount, t_symbol *unitname, + t_float *unit, int *samps) +{ + char *s = unitname->s_name; + if (amount <= 0) + amount = 1; + if (s[0] == 'p' && s[1] == 'e' && s[2] == 'r') /* starts with 'per' */ + { + char *s2 = s+3; + if (!strcmp(s2, "millisecond") || !strcmp(s2, "msec")) /* msec */ + *samps = 0, *unit = 1./amount; + else if (!strncmp(s2, "sec", 3)) /* seconds */ + *samps = 0, *unit = 1000./amount; + else if (!strncmp(s2, "min", 3)) /* minutes */ + *samps = 0, *unit = 60000./amount; + else if (!strncmp(s2, "sam", 3)) /* samples */ + *samps = 1, *unit = 1./amount; + else goto fail; + } + else + { + /* empty string defaults to msec */ + if (!strcmp(s, "millisecond") || !strcmp(s, "msec")) + *samps = 0, *unit = amount; + else if (!strncmp(s, "sec", 3)) + *samps = 0, *unit = 1000.*amount; + else if (!strncmp(s, "min", 3)) + *samps = 0, *unit = 60000.*amount; + else if (!strncmp(s, "sam", 3)) + *samps = 1, *unit = amount; + else + { + fail: + /* empty time unit specification defaults to 1 msec for + back compatibility, since it's possible someone threw a + float argument to timer which had previously been ignored. */ + if (*s) + pd_error(x, "%s: unknown time unit", s); + else pd_error(x, + "tempo setting needs time unit ('sec', 'samp', 'permin', etc."); + *unit = 1; + *samps = 0; + } + } +} + +/* -------------------------- delay ------------------------------ */ +static t_class *delay_class; + +typedef struct _delay +{ + t_object x_obj; + t_clock *x_clock; + double x_deltime; +} t_delay; + +static void delay_ft1(t_delay *x, t_floatarg g) +{ + if (g < 0) g = 0; + x->x_deltime = g; +} + +static void delay_tick(t_delay *x) +{ + outlet_bang(x->x_obj.ob_outlet); +} + +static void delay_bang(t_delay *x) +{ + clock_delay(x->x_clock, x->x_deltime); +} + +static void delay_stop(t_delay *x) +{ + clock_unset(x->x_clock); +} + +static void delay_float(t_delay *x, t_float f) +{ + delay_ft1(x, f); + delay_bang(x); +} + +static void delay_tempo(t_delay *x, t_symbol *unitname, t_floatarg tempo) +{ + t_float unit; + int samps; + parsetimeunits(x, tempo, unitname, &unit, &samps); + clock_setunit(x->x_clock, unit, samps); +} + +static void delay_free(t_delay *x) +{ + clock_free(x->x_clock); +} + +static void *delay_new(t_symbol *unitname, t_floatarg f, t_floatarg tempo) +{ + t_delay *x = (t_delay *)pd_new(delay_class); + delay_ft1(x, f); + x->x_clock = clock_new(x, (t_method)delay_tick); + outlet_new(&x->x_obj, gensym("bang")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1")); + if (tempo != 0) + delay_tempo(x, unitname, tempo); + return (x); +} + +static void delay_setup(void) +{ + delay_class = class_new(gensym("delay"), (t_newmethod)delay_new, + (t_method)delay_free, sizeof(t_delay), 0, + A_DEFFLOAT, A_DEFFLOAT, A_DEFSYM, 0); + class_addcreator((t_newmethod)delay_new, gensym("del"), + A_DEFFLOAT, A_DEFFLOAT, A_DEFSYM, 0); + class_addbang(delay_class, delay_bang); + class_addmethod(delay_class, (t_method)delay_stop, gensym("stop"), 0); + class_addmethod(delay_class, (t_method)delay_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(delay_class, (t_method)delay_tempo, + gensym("tempo"), A_FLOAT, A_SYMBOL, 0); + class_addfloat(delay_class, (t_method)delay_float); +} + +/* -------------------------- metro ------------------------------ */ +static t_class *metro_class; + +typedef struct _metro +{ + t_object x_obj; + t_clock *x_clock; + double x_deltime; + int x_hit; +} t_metro; + +static void metro_ft1(t_metro *x, t_floatarg g) +{ + if (g <= 0) /* as of 0.45, we're willing to try any positive time value */ + g = 1; /* but default to 1 (arbitrary and probably not so good) */ + x->x_deltime = g; +} + +static void metro_tick(t_metro *x) +{ + x->x_hit = 0; + outlet_bang(x->x_obj.ob_outlet); + if (!x->x_hit) clock_delay(x->x_clock, x->x_deltime); +} + +static void metro_float(t_metro *x, t_float f) +{ + if (f != 0) metro_tick(x); + else clock_unset(x->x_clock); + x->x_hit = 1; +} + +static void metro_bang(t_metro *x) +{ + metro_float(x, 1); +} + +static void metro_stop(t_metro *x) +{ + metro_float(x, 0); +} + +static void metro_tempo(t_metro *x, t_symbol *unitname, t_floatarg tempo) +{ + t_float unit; + int samps; + parsetimeunits(x, tempo, unitname, &unit, &samps); + clock_setunit(x->x_clock, unit, samps); +} + +static void metro_free(t_metro *x) +{ + clock_free(x->x_clock); +} + +static void *metro_new(t_symbol *unitname, t_floatarg f, t_floatarg tempo) +{ + t_metro *x = (t_metro *)pd_new(metro_class); + metro_ft1(x, f); + x->x_hit = 0; + x->x_clock = clock_new(x, (t_method)metro_tick); + outlet_new(&x->x_obj, gensym("bang")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1")); + if (tempo != 0) + metro_tempo(x, unitname, tempo); + return (x); +} + +static void metro_setup(void) +{ + metro_class = class_new(gensym("metro"), (t_newmethod)metro_new, + (t_method)metro_free, sizeof(t_metro), 0, + A_DEFFLOAT, A_DEFFLOAT, A_DEFSYM, 0); + class_addbang(metro_class, metro_bang); + class_addmethod(metro_class, (t_method)metro_stop, gensym("stop"), 0); + class_addmethod(metro_class, (t_method)metro_ft1, gensym("ft1"), + A_FLOAT, 0); + class_addmethod(metro_class, (t_method)metro_tempo, + gensym("tempo"), A_FLOAT, A_SYMBOL, 0); + class_addfloat(metro_class, (t_method)metro_float); +} + +/* -------------------------- line ------------------------------ */ +#define DEFAULTLINEGRAIN 20 +static t_class *line_class; + +typedef struct _line +{ + t_object x_obj; + t_clock *x_clock; + double x_targettime; + t_float x_targetval; + double x_prevtime; + t_float x_setval; + int x_gotinlet; + t_float x_grain; + double x_1overtimediff; + double x_in1val; +} t_line; + +static void line_tick(t_line *x) +{ + double timenow = clock_getsystime(); + double msectogo = - clock_gettimesince(x->x_targettime); + if (msectogo < 1E-9) + { + outlet_float(x->x_obj.ob_outlet, x->x_targetval); + } + else + { + outlet_float(x->x_obj.ob_outlet, + x->x_setval + x->x_1overtimediff * (timenow - x->x_prevtime) + * (x->x_targetval - x->x_setval)); + if (x->x_grain <= 0) + x->x_grain = DEFAULTLINEGRAIN; + clock_delay(x->x_clock, + (x->x_grain > msectogo ? msectogo : x->x_grain)); + } +} + +static void line_float(t_line *x, t_float f) +{ + double timenow = clock_getsystime(); + if (x->x_gotinlet && x->x_in1val > 0) + { + if (timenow > x->x_targettime) x->x_setval = x->x_targetval; + else x->x_setval = x->x_setval + x->x_1overtimediff * + (timenow - x->x_prevtime) + * (x->x_targetval - x->x_setval); + x->x_prevtime = timenow; + x->x_targettime = clock_getsystimeafter(x->x_in1val); + x->x_targetval = f; + line_tick(x); + x->x_gotinlet = 0; + x->x_1overtimediff = 1./ (x->x_targettime - timenow); + if (x->x_grain <= 0) + x->x_grain = DEFAULTLINEGRAIN; + clock_delay(x->x_clock, + (x->x_grain > x->x_in1val ? x->x_in1val : x->x_grain)); + + } + else + { + clock_unset(x->x_clock); + x->x_targetval = x->x_setval = f; + outlet_float(x->x_obj.ob_outlet, f); + } + x->x_gotinlet = 0; +} + +static void line_ft1(t_line *x, t_floatarg g) +{ + x->x_in1val = g; + x->x_gotinlet = 1; +} + +static void line_stop(t_line *x) +{ + if (pd_compatibilitylevel >= 48) + x->x_setval += x->x_1overtimediff * (clock_getsystime() - x->x_prevtime) + * (x->x_targetval - x->x_setval); + x->x_targetval = x->x_setval; + clock_unset(x->x_clock); +} + +static void line_set(t_line *x, t_floatarg f) +{ + clock_unset(x->x_clock); + x->x_targetval = x->x_setval = f; +} + +static void line_free(t_line *x) +{ + clock_free(x->x_clock); +} + +static void *line_new(t_floatarg f, t_floatarg grain) +{ + t_line *x = (t_line *)pd_new(line_class); + x->x_targetval = x->x_setval = f; + x->x_gotinlet = 0; + x->x_1overtimediff = 1; + x->x_clock = clock_new(x, (t_method)line_tick); + x->x_targettime = x->x_prevtime = clock_getsystime(); + x->x_grain = grain; + outlet_new(&x->x_obj, gensym("float")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1")); + floatinlet_new(&x->x_obj, &x->x_grain); + return (x); +} + +static void line_setup(void) +{ + line_class = class_new(gensym("line"), (t_newmethod)line_new, + (t_method)line_free, sizeof(t_line), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(line_class, (t_method)line_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(line_class, (t_method)line_stop, + gensym("stop"), 0); + class_addmethod(line_class, (t_method)line_set, + gensym("set"), A_FLOAT, 0); + class_addfloat(line_class, (t_method)line_float); +} + +/* -------------------------- timer ------------------------------ */ +static t_class *timer_class; + +typedef struct _timer +{ + t_object x_obj; + double x_settime; + double x_moreelapsed; + t_float x_unit; + int x_samps; +} t_timer; + +static void timer_bang(t_timer *x) +{ + x->x_settime = clock_getsystime(); + x->x_moreelapsed = 0; +} + +static void timer_bang2(t_timer *x) +{ + outlet_float(x->x_obj.ob_outlet, + clock_gettimesincewithunits(x->x_settime, x->x_unit, x->x_samps) + + x->x_moreelapsed); +} + +static void timer_tempo(t_timer *x, t_symbol *unitname, t_floatarg tempo) +{ + x->x_moreelapsed += clock_gettimesincewithunits(x->x_settime, + x->x_unit, x->x_samps); + x->x_settime = clock_getsystime(); + parsetimeunits(x, tempo, unitname, &x->x_unit, &x->x_samps); +} + +static void *timer_new(t_symbol *unitname, t_floatarg tempo) +{ + t_timer *x = (t_timer *)pd_new(timer_class); + x->x_unit = 1; + x->x_samps = 0; + timer_bang(x); + outlet_new(&x->x_obj, gensym("float")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("bang"), gensym("bang2")); + if (tempo != 0) + timer_tempo(x, unitname, tempo); + return (x); +} + +static void timer_setup(void) +{ + timer_class = class_new(gensym("timer"), (t_newmethod)timer_new, 0, + sizeof(t_timer), 0, A_DEFFLOAT, A_DEFSYM, 0); + class_addbang(timer_class, timer_bang); + class_addmethod(timer_class, (t_method)timer_bang2, gensym("bang2"), 0); + class_addmethod(timer_class, (t_method)timer_tempo, + gensym("tempo"), A_FLOAT, A_SYMBOL, 0); +} + + +/* -------------------------- pipe -------------------------- */ + +static t_class *pipe_class; + +typedef struct _hang +{ + t_clock *h_clock; + struct _hang *h_next; + struct _pipe *h_owner; + t_gpointer *h_gp; + union word h_vec[1]; /* not the actual number. */ +} t_hang; + +typedef struct pipeout +{ + t_atom p_atom; + t_outlet *p_outlet; +} t_pipeout; + +typedef struct _pipe +{ + t_object x_obj; + int x_n; + int x_nptr; + t_float x_deltime; + t_pipeout *x_vec; + t_gpointer *x_gp; + t_hang *x_hang; +} t_pipe; + +static void *pipe_new(t_symbol *s, int argc, t_atom *argv) +{ + t_pipe *x = (t_pipe *)pd_new(pipe_class); + t_atom defarg, *ap; + t_pipeout *vec, *vp; + t_gpointer *gp; + int nptr = 0; + int i; + t_float deltime; + if (argc) + { + if (argv[argc-1].a_type != A_FLOAT) + { + char stupid[80]; + atom_string(&argv[argc-1], stupid, 79); + pd_error(x, "pipe: %s: bad time delay value", stupid); + deltime = 0; + } + else deltime = argv[argc-1].a_w.w_float; + argc--; + } + else deltime = 0; + if (!argc) + { + argv = &defarg; + argc = 1; + SETFLOAT(&defarg, 0); + } + x->x_n = argc; + vec = x->x_vec = (t_pipeout *)getbytes(argc * sizeof(*x->x_vec)); + + for (i = argc, ap = argv; i--; ap++) + if (ap->a_type == A_SYMBOL && *ap->a_w.w_symbol->s_name == 'p') + nptr++; + + gp = x->x_gp = (t_gpointer *)t_getbytes(nptr * sizeof (*gp)); + x->x_nptr = nptr; + + for (i = 0, vp = vec, ap = argv; i < argc; i++, ap++, vp++) + { + if (ap->a_type == A_FLOAT) + { + vp->p_atom = *ap; + vp->p_outlet = outlet_new(&x->x_obj, &s_float); + if (i) floatinlet_new(&x->x_obj, &vp->p_atom.a_w.w_float); + } + else if (ap->a_type == A_SYMBOL) + { + char c = *ap->a_w.w_symbol->s_name; + if (c == 's') + { + SETSYMBOL(&vp->p_atom, &s_symbol); + vp->p_outlet = outlet_new(&x->x_obj, &s_symbol); + if (i) symbolinlet_new(&x->x_obj, &vp->p_atom.a_w.w_symbol); + } + else if (c == 'p') + { + vp->p_atom.a_type = A_POINTER; + vp->p_atom.a_w.w_gpointer = gp; + gpointer_init(gp); + vp->p_outlet = outlet_new(&x->x_obj, &s_pointer); + if (i) pointerinlet_new(&x->x_obj, gp); + gp++; + } + else + { + if (c != 'f') pd_error(x, "pipe: %s: bad type", + ap->a_w.w_symbol->s_name); + SETFLOAT(&vp->p_atom, 0); + vp->p_outlet = outlet_new(&x->x_obj, &s_float); + if (i) floatinlet_new(&x->x_obj, &vp->p_atom.a_w.w_float); + } + } + } + floatinlet_new(&x->x_obj, &x->x_deltime); + x->x_hang = 0; + x->x_deltime = deltime; + return (x); +} + +static void hang_free(t_hang *h) +{ + t_pipe *x = h->h_owner; + t_gpointer *gp; + int i; + for (gp = h->h_gp, i = x->x_nptr; i--; gp++) + gpointer_unset(gp); + freebytes(h->h_gp, x->x_nptr * sizeof(*h->h_gp)); + clock_free(h->h_clock); + freebytes(h, sizeof(*h) + (x->x_n - 1) * sizeof(*h->h_vec)); +} + +static void hang_tick(t_hang *h) +{ + t_pipe *x = h->h_owner; + t_hang *h2, *h3; + t_pipeout *p; + int i; + union word *w; + if (x->x_hang == h) x->x_hang = h->h_next; + else for (h2 = x->x_hang; (h3 = h2->h_next); h2 = h3) + { + if (h3 == h) + { + h2->h_next = h3->h_next; + break; + } + } + for (i = x->x_n, p = x->x_vec + (x->x_n - 1), w = h->h_vec + (x->x_n - 1); + i--; p--, w--) + { + switch (p->p_atom.a_type) + { + case A_FLOAT: outlet_float(p->p_outlet, w->w_float); break; + case A_SYMBOL: outlet_symbol(p->p_outlet, w->w_symbol); break; + case A_POINTER: + if (gpointer_check(w->w_gpointer, 1)) + outlet_pointer(p->p_outlet, w->w_gpointer); + else pd_error(x, "pipe: stale pointer"); + break; + default: break; + } + } + hang_free(h); +} + +static void pipe_list(t_pipe *x, t_symbol *s, int ac, t_atom *av) +{ + t_hang *h = (t_hang *) + getbytes(sizeof(*h) + (x->x_n - 1) * sizeof(*h->h_vec)); + t_gpointer *gp, *gp2; + t_pipeout *p; + int i, n = x->x_n; + t_atom *ap; + t_word *w; + h->h_gp = (t_gpointer *)getbytes(x->x_nptr * sizeof(t_gpointer)); + if (ac > n) + { + if (av[n].a_type == A_FLOAT) + x->x_deltime = av[n].a_w.w_float; + else pd_error(x, "pipe: symbol or pointer in time inlet"); + ac = n; + } + for (i = 0, gp = x->x_gp, p = x->x_vec, ap = av; i < ac; + i++, p++, ap++) + { + switch (p->p_atom.a_type) + { + case A_FLOAT: p->p_atom.a_w.w_float = atom_getfloat(ap); break; + case A_SYMBOL: p->p_atom.a_w.w_symbol = atom_getsymbol(ap); break; + case A_POINTER: + gpointer_unset(gp); + if (ap->a_type != A_POINTER) + pd_error(x, "pipe: bad pointer"); + else + { + *gp = *(ap->a_w.w_gpointer); + if (gp->gp_stub) gp->gp_stub->gs_refcount++; + } + gp++; + default: break; + } + } + for (i = 0, gp = x->x_gp, gp2 = h->h_gp, p = x->x_vec, w = h->h_vec; + i < n; i++, p++, w++) + { + if (p->p_atom.a_type == A_POINTER) + { + if (gp->gp_stub) gp->gp_stub->gs_refcount++; + w->w_gpointer = gp2; + *gp2++ = *gp++; + } + else *w = p->p_atom.a_w; + } + h->h_next = x->x_hang; + x->x_hang = h; + h->h_owner = x; + h->h_clock = clock_new(h, (t_method)hang_tick); + clock_delay(h->h_clock, (x->x_deltime >= 0 ? x->x_deltime : 0)); +} + +static void pipe_flush(t_pipe *x) +{ + while (x->x_hang) hang_tick(x->x_hang); +} + +static void pipe_clear(t_pipe *x) +{ + t_hang *hang; + while ((hang = x->x_hang)) + { + x->x_hang = hang->h_next; + hang_free(hang); + } +} + +static void pipe_free(t_pipe *x) +{ + pipe_clear(x); + freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec)); + freebytes(x->x_gp, x->x_nptr * sizeof(*x->x_gp)); + +} + +static void pipe_setup(void) +{ + pipe_class = class_new(gensym("pipe"), + (t_newmethod)pipe_new, (t_method)pipe_free, + sizeof(t_pipe), 0, A_GIMME, 0); + class_addlist(pipe_class, pipe_list); + class_addmethod(pipe_class, (t_method)pipe_flush, gensym("flush"), 0); + class_addmethod(pipe_class, (t_method)pipe_clear, gensym("clear"), 0); +} + +void x_time_setup(void) +{ + delay_setup(); + metro_setup(); + line_setup(); + timer_setup(); + pipe_setup(); +} diff --git a/ports/camomile/source/LibPd/pure-data/src/x_vexp.c b/ports/camomile/source/LibPd/pure-data/src/x_vexp.c new file mode 100644 index 00000000..19da8ba9 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_vexp.c @@ -0,0 +1,2202 @@ +/* Copyright (c) IRCAM. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* "expr" was written by Shahrokh Yadegari c. 1989. -msp */ +/* "expr~" and "fexpr~" conversion by Shahrokh Yadegari c. 1999,2000 */ + + +/* + * Feb 2002 - added access to variables + * multiple expression support + * new short hand forms for fexpr~ + * now $y or $y1 = $y1[-1] and $y2 = $y2[-1] + * --sdy + * + * July 2002 + * fixed bugs introduced in last changes in store and ET_EQ + * --sdy + * + * Oct 2015 + * $x[-1] was not equal $x1[-1], not accessing the previous block + * (bug fix by Dan Ellis) + * + * July 2017 --sdy + * - Version 0.55 + * + * - The arrays now redraw after a store into one of their members + * - ex_if() (the "if()" function is reworked to only evaluate either + * the left or the right args depending on the truth value of the condition. + * However, if the condition is a vector, both the left and the right + * are evaluated regradless. + * - priority of ',' and '=' was switched to fix the bug of using store "=" in + * functions with multiple arguments, which caused an error during execution. + * - The number of inlet and outlets (MAX_VARS) is now set at 100 + * + * - Version 0.56 + * -fexpr~ now accepts a float in its first input + * -Added avg() and Avg() back to the list of functions + */ + +/* + * vexp.c -- a variable expression evaluator + * + * This modules implements an expression evaluator using the + * operator-precedence parsing. It transforms an infix expression + * to a prefix stack ready to be evaluated. The expression sysntax + * is close to that of C. There are a few operators that are not + * supported and functions are also recognized. Strings can be + * passed to functions when they are quoted in '"'s. "[]" are implemented + * as an easy way of accessing the content of tables, and the syntax + * table_name[index]. + * Variables (inlets) are specified with the following syntax: $x#, + * where x is either i(integers), f(floats), and s(strings); and # + * is a digit that corresponds to the inlet number. The string variables + * can be used as strings when they are quoted and can also be used as + * table names when they are followed by "[]". + * + * signal vectors have been added to this implementation: + * $v# denotes a signal vector + * $x#[index] is the value of a sample at the index of a the signal vector + * $x# is the shorthand for $x#[0] + * $y[index] is the value of the sample output at the index of a the + * signal output + * "index" for $x#[index] has to have this range (0 <= index < vectorsize) + * "index" for $y[index] has to have this range (0 < index < vectorsize) + */ + +#include +#include +#include +#include "x_vexp.h" +#include +#ifdef MSP +#undef isdigit +#define isdigit(x) (x >= '0' && x <= '9') +#endif + +#ifdef _MSC_VER +#define strtof(a, b) _atoldbl(a, *b) +#endif + + +char *atoif(char *s, long int *value, long int *type); + +static struct ex_ex *ex_lex(struct expr *expr, long int *n); +struct ex_ex *ex_match(struct ex_ex *eptr, long int op); +struct ex_ex *ex_parse(struct expr *expr, struct ex_ex *iptr, + struct ex_ex *optr, long int *argc); +struct ex_ex *ex_eval(struct expr *expr, struct ex_ex *eptr, + struct ex_ex *optr, int i); + +int expr_donew(struct expr *exprr, int ac, t_atom *av); +struct ex_ex *eval_func(struct expr *expr,struct ex_ex *eptr, + struct ex_ex *optr, int i); +struct ex_ex *eval_tab(struct expr *expr, struct ex_ex *eptr, + struct ex_ex *optr, int i); +struct ex_ex *eval_var(struct expr *expr, struct ex_ex *eptr, + struct ex_ex *optr, int i); +struct ex_ex *eval_store(struct expr *expr, struct ex_ex *eptr, + struct ex_ex *optr, int i); +struct ex_ex *eval_sigidx(struct expr *expr, struct ex_ex *eptr, + struct ex_ex *optr, int i); +static int cal_sigidx(struct ex_ex *optr, /* The output value */ + int i, t_float rem_i, /* integer and fractinal part of index */ + int idx, /* index of current fexpr~ processing */ + int vsize, /* vector size */ + t_float *curvec, t_float *prevec); /* current and previous table */ +t_ex_func *find_func(char *s); +void ex_dzdetect(struct expr *expr); + +#define MAX_ARGS 10 +extern t_ex_func ex_funcs[]; + +struct ex_ex nullex; + +void set_tokens (char *s); +int getoken (struct expr *expr, struct ex_ex *eptr); +void ex_print (struct ex_ex *eptr); +#ifdef MSP +void atom_string(t_atom *a, char *buf, unsigned int bufsize); + +void atom_string(t_atom *a, char *buf, unsigned int bufsize) +{ + char tbuf[30]; + switch(a->a_type) + { + case A_SEMI: strcpy(buf, ";"); break; + case A_COMMA: strcpy(buf, ","); break; +#ifdef PD + case A_POINTER: + strcpy(buf, "(pointer)"); + break; +#endif + case A_FLOAT: + sprintf(tbuf, "%g", a->a_w.w_float); + if (strlen(tbuf) < bufsize-1) strcpy(buf, tbuf); + else if (a->a_w.w_float < 0) strcpy(buf, "-"); + else strcat(buf, "+"); + break; + case A_LONG: + sprintf(tbuf, "%d", a->a_w.w_long); + if (strlen(tbuf) < bufsize-1) strcpy(buf, tbuf); + else if (a->a_w.w_float < 0) strcpy(buf, "-"); + else strcat(buf, "+"); + break; + case A_SYMBOL: + { + char *sp; + unsigned int len; + int quote; + for (sp = a->a_w.w_symbol->s_name, len = 0, quote = 0; *sp; sp++, len++) + if (*sp == ';' || *sp == ',' || *sp == '\\' || + (*sp == '$' && sp == a->a_w.w_symbol->s_name && sp[1] >= '0' + && sp[1] <= '9')) + quote = 1; + if (quote) + { + char *bp = buf, *ep = buf + (bufsize-2); + sp = a->a_w.w_symbol->s_name; + while (bp < ep && *sp) + { + if (*sp == ';' || *sp == ',' || *sp == '\\' || + (*sp == '$' && bp == buf && sp[1] >= '0' && sp[1] <= '9')) + *bp++ = '\\'; + *bp++ = *sp++; + } + if (*sp) *bp++ = '*'; + *bp = 0; + /* post("quote %s -> %s", a->a_w.w_symbol->s_name, buf); */ + } + else + { + if (len < bufsize-1) strcpy(buf, a->a_w.w_symbol->s_name); + else + { + strncpy(buf, a->a_w.w_symbol->s_name, bufsize - 2); + strcpy(buf + (bufsize - 2), "*"); + } + } + } + break; +#ifdef PD + case A_DOLLAR: + sprintf(buf, "$%d", a->a_w.w_index); + break; + case A_DOLLSYM: + sprintf(buf, "$%s", a->a_w.w_symbol->s_name); + break; +#else /* MAX */ + case A_DOLLAR: + sprintf(buf, "$%s", a->a_w.w_symbol->s_name); + break; +#endif + default: + post("atom_string bug"); + } +} +#endif /* MSP */ +/* + * expr_donew -- create a new "expr" object. + * returns 1 on failure, 0 on success. + */ +int +expr_donew(struct expr *expr, int ac, t_atom *av) +{ + struct ex_ex *list; + struct ex_ex *ret; + long max_node = 0; /* maximum number of nodes needed */ + char *exp_string; + int exp_strlen; + t_binbuf *b; + int i; + + memset(expr->exp_var, 0, MAX_VARS * sizeof (*expr->exp_var)); +#ifdef PD + b = binbuf_new(); + binbuf_add(b, ac, av); + binbuf_gettext(b, &exp_string, &exp_strlen); + binbuf_free(b); +#else /* MSP */ + { + char *buf = getbytes(0), *newbuf; + int length = 0; + char string[250]; + t_atom *ap; + int indx; + + for (ap = av, indx = 0; indx < ac; indx++, ap = ++av) { + int newlength; + + if ((ap->a_type == A_SEMI || ap->a_type == A_COMMA) && + length && buf[length-1] == ' ') + length--; + atom_string(ap, string, 250); + newlength = length + strlen(string) + 1; + if (!(newbuf = t_resizebytes(buf, length, newlength))) + break; + buf = newbuf; + strcpy(buf + length, string); + length = newlength; + if (ap->a_type == A_SEMI) + buf[length-1] = '\n'; + else + buf[length-1] = ' '; + } + + if (length && buf[length-1] == ' ') { + if (newbuf = t_resizebytes(buf, length, length-1)) + { + buf = newbuf; + length--; + } + } + exp_string = buf; + exp_strlen = length; + } +#endif + exp_string = (char *)t_resizebytes(exp_string, exp_strlen,exp_strlen+1); + exp_string[exp_strlen] = 0; + expr->exp_string = exp_string; + expr->exp_str = exp_string; + expr->exp_nexpr = 0; + ret = (struct ex_ex *) 0; + /* + * if ret == 0 it means that we have no expression + * so we let the pass go through to build a single null stack + */ + while (*expr->exp_str || !ret) { + list = ex_lex(expr, &max_node); + if (!list) { /* syntax error */ + goto error; + } + expr->exp_stack[expr->exp_nexpr] = + (struct ex_ex *)fts_malloc(max_node * sizeof (struct ex_ex)); + if (!expr->exp_stack[expr->exp_nexpr]) { + post_error( (fts_object_t *) expr, + "expr: malloc for expr nodes failed\n"); + goto error; + } + expr->exp_stack[expr->exp_nexpr][max_node-1].ex_type=0; + expr->exp_nexpr++; + ret = ex_match(list, (long)0); + if (expr->exp_nexpr > MAX_VARS) + /* we cannot exceed MAX_VARS '$' variables */ + { + post_error((fts_object_t *) expr, + "expr: too many variables (maximum %d allowed)", + MAX_VARS); + goto error; + } + if (!ret) /* syntax error */ + goto error; + ret = ex_parse(expr, + list, expr->exp_stack[expr->exp_nexpr - 1], (long *)0); + if (!ret) + goto error; + fts_free(list); + } + *ret = nullex; + t_freebytes(exp_string, exp_strlen+1); + return (0); +error: + for (i = 0; i < expr->exp_nexpr; i++) { + fts_free(expr->exp_stack[i]); + expr->exp_stack[i] = 0; + } + expr->exp_nexpr = 0; + if (list) + fts_free(list); + t_freebytes(exp_string, exp_strlen+1); + return (1); +} + +/* + * ex_lex -- This routine is a bit more than a lexical parser since it will + * also do some syntax checking. It reads the string s and will + * return a linked list of struct ex_ex. + * It will also put the number of the nodes in *n. + */ +struct ex_ex * +ex_lex(struct expr *expr, long int *n) +{ + struct ex_ex *list_arr; + struct ex_ex *exptr; + long non = 0; /* number of nodes */ + long maxnode = 0; + + list_arr = (struct ex_ex *)fts_malloc(sizeof (struct ex_ex) * MINODES); + if (! list_arr) { + post("ex_lex: no mem\n"); + return ((struct ex_ex *)0); + } + exptr = list_arr; + maxnode = MINODES; + + while (8) + { + if (non >= maxnode) { + maxnode += MINODES; + + list_arr = fts_realloc((void *)list_arr, + sizeof (struct ex_ex) * maxnode); + if (!list_arr) { + post("ex_lex: no mem\n"); + return ((struct ex_ex *)0); + } + exptr = &(list_arr)[non]; + } + + if (getoken(expr, exptr)) { + fts_free(list_arr); + return ((struct ex_ex *)0); + } + non++; + + if (!exptr->ex_type) + break; + + exptr++; + } + *n = non; + + return list_arr; +} + +/* + * ex_match -- this routine walks through the eptr and matches the + * perentheses and brackets, it also converts the function + * names to a pointer to the describing structure of the + * specified function + */ +/* operator to match */ +struct ex_ex * +ex_match(struct ex_ex *eptr, long int op) +{ + int firstone = 1; + struct ex_ex *ret; + t_ex_func *fun; + + for (; 8; eptr++, firstone = 0) { + switch (eptr->ex_type) { + case 0: + if (!op) + return (eptr); + post("expr syntax error: an open %s not matched\n", + op == OP_RP ? "parenthesis" : "bracket"); + return (exNULL); + case ET_INT: + case ET_FLT: + case ET_II: + case ET_FI: + case ET_SI: + case ET_VI: + case ET_SYM: + case ET_VSYM: + continue; + case ET_YO: + if (eptr[1].ex_type != ET_OP || eptr[1].ex_op != OP_LB) + eptr->ex_type = ET_YOM1; + continue; + case ET_XI: + if (eptr[1].ex_type != ET_OP || eptr[1].ex_op != OP_LB) + eptr->ex_type = ET_XI0; + continue; + /* + * tables, functions, parenthesis, and brackets, are marked as + * operations, and they are assigned their proper operation + * in this function. Thus, if we arrive to any of these in this + * type tokens at this location, we must have had some error + */ + case ET_TBL: + case ET_FUNC: + case ET_LP: + case ET_LB: + post("ex_match: unexpected type, %ld\n", eptr->ex_type); + return (exNULL); + case ET_OP: + if (op == eptr->ex_op) + return (eptr); + /* + * if we are looking for a right peranthesis + * or a right bracket and find the other kind, + * it has to be a syntax error + */ + if ((eptr->ex_op == OP_RP && op == OP_RB) || + (eptr->ex_op == OP_RB && op == OP_RP)) { + post("expr syntax error: prenthesis or brackets not matched\n"); + return (exNULL); + } + /* + * Up to now we have marked the unary minuses as + * subrtacts. Any minus that is the first one in + * chain or is preceded by anything except ')' and + * ']' is a unary minus. + */ + if (eptr->ex_op == OP_SUB) { + ret = eptr - 1; + if (firstone || (ret->ex_type == ET_OP && + ret->ex_op != OP_RB && ret->ex_op != OP_RP)) + eptr->ex_op = OP_UMINUS; + } else if (eptr->ex_op == OP_LP) { + ret = ex_match(eptr + 1, OP_RP); + if (!ret) + return (ret); + eptr->ex_type = ET_LP; + eptr->ex_ptr = (char *) ret; + eptr = ret; + } else if (eptr->ex_op == OP_LB) { + ret = ex_match(eptr + 1, OP_RB); + if (!ret) + return (ret); + /* + * this is a special case handling + * for $1, $2 processing in Pd + * + * Pure data translates $#[x] (e.g. $1[x]) to 0[x] + * for abstracting patches so that later + * in the instantiation of the abstraction + * the $# is replaced with the proper argument + * of the abstraction + * so we change 0[x] to a special table pointing to null + * and catch errors in execution time + */ + if (!firstone && (eptr - 1)->ex_type == ET_INT && + ((eptr - 1)->ex_int == 0)) { + (eptr - 1)->ex_type = ET_TBL; + (eptr - 1)->ex_ptr = (char *)0; + } + eptr->ex_type = ET_LB; + eptr->ex_ptr = (char *) ret; + eptr = ret; + } + continue; + case ET_STR: + if (eptr[1].ex_op == OP_LB) { + char *tmp; + + eptr->ex_type = ET_TBL; + tmp = eptr->ex_ptr; + if (ex_getsym(tmp, (t_symbol **)&(eptr->ex_ptr))) { + post("expr: syntax error: problms with ex_getsym\n"); + return (exNULL); + } + fts_free((void *)tmp); + } else if (eptr[1].ex_op == OP_LP) { + fun = find_func(eptr->ex_ptr); + if (!fun) { + post( + "expr: error: function %s not found\n", + eptr->ex_ptr); + return (exNULL); + } + eptr->ex_type = ET_FUNC; + eptr->ex_ptr = (char *) fun; + } else { + char *tmp; + + if (eptr[1].ex_type && eptr[1].ex_type!=ET_OP){ + post("expr: syntax error: bad string '%s'\n", eptr->ex_ptr); + return (exNULL); + } + /* it is a variable */ + eptr->ex_type = ET_VAR; + tmp = eptr->ex_ptr; + if (ex_getsym(tmp, + (t_symbol **)&(eptr->ex_ptr))) { + post("expr: variable '%s' not found",tmp); + return (exNULL); + } + } + continue; + default: + post("ex_match: bad type\n"); + return (exNULL); + } + } + /* NOTREACHED */ +} + +/* + * ex_parse -- This function is called when we have already done some + * parsing on the expression, and we have already matched + * our brackets and parenthesis. The main job of this + * function is to convert the infix expression to the + * prefix form. + * First we find the operator with the lowest precedence and + * put it on the stack ('optr', it is really just an array), then + * we call ourself (ex_parse()), on its arguments (unary operators + * only have one operator.) + * When "argc" is set it means that we are parsing the arguments + * of a function and we will increment *argc anytime we find + * a segment that can qualify as an argument (counting commas). + * + * returns 0 on syntax error + */ +/* number of argument separated by comma */ +struct ex_ex * +ex_parse(struct expr *x, struct ex_ex *iptr, struct ex_ex *optr, long int *argc) +{ + struct ex_ex *eptr; + struct ex_ex *lowpre = 0; /* pointer to the lowest precedence */ + struct ex_ex savex; + struct ex_ex *tmpex; + long pre = HI_PRE; + long count; + + if (!iptr) { + post("ex_parse: input is null, iptr = 0x%lx\n", iptr); + return (exNULL); + } + if (!iptr->ex_type) + return (exNULL); + + /* + * the following loop finds the lowest precedence operator in the + * the input token list, comma is explicitly checked here since + * that is a special operator and is only legal in functions + */ + for (eptr = iptr, count = 0; eptr->ex_type; eptr++, count++) + switch (eptr->ex_type) { + case ET_SYM: + case ET_VSYM: + if (!argc) { + post("expr: syntax error: symbols allowed for functions only\n"); + ex_print(eptr); + return (exNULL); + } /* falls through */ + case ET_INT: + case ET_FLT: + case ET_II: + case ET_FI: + case ET_XI0: + case ET_YOM1: + case ET_VI: + case ET_VAR: + if (!count && !eptr[1].ex_type) { + *optr = *eptr; + tmpex = optr; + tmpex->ex_end = ++optr; + return (optr); + } + break; + case ET_XI: + case ET_YO: + case ET_SI: + case ET_TBL: + if (eptr[1].ex_type != ET_LB) { + post("expr: syntax error: brackets missing\n"); + ex_print(eptr); + return (exNULL); + } + /* if this table is the only token, parse the table */ + if (!count && + !((struct ex_ex *) eptr[1].ex_ptr)[1].ex_type) { + savex = *((struct ex_ex *) eptr[1].ex_ptr); + *((struct ex_ex *) eptr[1].ex_ptr) = nullex; + *optr = *eptr; + lowpre = ex_parse(x, &eptr[2], optr + 1, (long *)0); + *((struct ex_ex *) eptr[1].ex_ptr) = savex; + optr->ex_end = lowpre; + return(lowpre); + } + eptr = (struct ex_ex *) eptr[1].ex_ptr; + break; + case ET_OP: + if (eptr->ex_op == OP_COMMA) { + if (!argc || !count || !eptr[1].ex_type) { + post("expr: syntax error: illegal comma\n"); + ex_print(eptr[1].ex_type ? eptr : iptr); + return (exNULL); + } + } + if (!eptr[1].ex_type) { + post("expr: syntax error: missing operand\n"); + ex_print(iptr); + return (exNULL); + } + if ((eptr->ex_op & PRE_MASK) <= pre) { + pre = eptr->ex_op & PRE_MASK; + lowpre = eptr; + } + break; + case ET_FUNC: + if (eptr[1].ex_type != ET_LP) { + post("expr: ex_parse: no parenthesis\n"); + return (exNULL); + } + /* if this function is the only token, parse it */ + if (!count && + !((struct ex_ex *) eptr[1].ex_ptr)[1].ex_type) { + long ac; + + if (eptr[1].ex_ptr == (char *) &eptr[2]) { + post("expr: syntax error: missing argument\n"); + ex_print(eptr); + return (exNULL); + } + ac = 0; + savex = *((struct ex_ex *) eptr[1].ex_ptr); + *((struct ex_ex *) eptr[1].ex_ptr) = nullex; + *optr = *eptr; + lowpre = ex_parse(x, &eptr[2], optr + 1, &ac); + if (!lowpre) + return (exNULL); + ac++; + if (ac != + ((t_ex_func *)eptr->ex_ptr)->f_argc){ + post("expr: syntax error: function '%s' needs %ld arguments\n", + ((t_ex_func *)eptr->ex_ptr)->f_name, + ((t_ex_func *)eptr->ex_ptr)->f_argc); + return (exNULL); + } + *((struct ex_ex *) eptr[1].ex_ptr) = savex; + optr->ex_end = lowpre; + return (lowpre); + } + eptr = (struct ex_ex *) eptr[1].ex_ptr; + break; + case ET_LP: + case ET_LB: + if (!count && + !((struct ex_ex *) eptr->ex_ptr)[1].ex_type) { + if (eptr->ex_ptr == (char *)(&eptr[1])) { + post("expr: syntax error: empty '%s'\n", + eptr->ex_type==ET_LP?"()":"[]"); + ex_print(eptr); + return (exNULL); + } + savex = *((struct ex_ex *) eptr->ex_ptr); + *((struct ex_ex *) eptr->ex_ptr) = nullex; + lowpre = ex_parse(x, &eptr[1], optr, (long *)0); + *((struct ex_ex *) eptr->ex_ptr) = savex; + optr->ex_end = lowpre; + return (lowpre); + } + eptr = (struct ex_ex *)eptr->ex_ptr; + break; + case ET_STR: + default: + ex_print(eptr); + post("expr: ex_parse: type = 0x%lx\n", eptr->ex_type); + return (exNULL); + } + + if (pre == HI_PRE) { + post("expr: syntax error: missing operation\n"); + ex_print(iptr); + return (exNULL); + } + if (count < 2) { + post("expr: syntax error: mission operand\n"); + ex_print(iptr); + return (exNULL); + } + if (count == 2) { + if (lowpre != iptr) { + post("expr: ex_parse: unary operator should be first\n"); + return (exNULL); + } + if (!unary_op(lowpre->ex_op)) { + post("expr: syntax error: not a uniary operator\n"); + ex_print(iptr); + return (exNULL); + } + *optr = *lowpre; + eptr = ex_parse(x, &lowpre[1], optr + 1, argc); + optr->ex_end = eptr; + return (eptr); + } + /* this is the case of using unary operator as a binary opetator */ + if (count == 3 && unary_op(lowpre->ex_op)) { + post("expr: syntax error, missing operand before unary operator\n"); + ex_print(iptr); + return (exNULL); + } + if (lowpre == iptr) { + post("expr: syntax error: mission operand\n"); + ex_print(iptr); + return (exNULL); + } + savex = *lowpre; + *lowpre = nullex; + if (savex.ex_op != OP_COMMA) { + *optr = savex; + eptr = ex_parse(x, iptr, optr + 1, argc); + } else { + (*argc)++; + eptr = ex_parse(x, iptr, optr, argc); + } + if (eptr) { + eptr = ex_parse(x, &lowpre[1], eptr, argc); + *lowpre = savex; + } + optr->ex_end = eptr; + return (eptr); +} + +/* + * this is the divide zero check for a non divide operator + */ +#define DZC(ARG1,OPR,ARG2) (ARG1 OPR ARG2) + +#define EVAL(OPR); \ +eptr = ex_eval(expr, ex_eval(expr, eptr, &left, idx), &right, idx); \ +switch (left.ex_type) { \ +case ET_INT: \ + switch(right.ex_type) { \ + case ET_INT: \ + if (optr->ex_type == ET_VEC) { \ + op = optr->ex_vec; \ + scalar = (t_float)DZC(left.ex_int, OPR, right.ex_int); \ + for (j = 0; j < expr->exp_vsize; j++) \ + *op++ = scalar; \ + } else { \ + optr->ex_type = ET_INT; \ + optr->ex_int = DZC(left.ex_int, OPR, right.ex_int); \ + } \ + break; \ + case ET_FLT: \ + if (optr->ex_type == ET_VEC) { \ + op = optr->ex_vec; \ + scalar = DZC(((t_float)left.ex_int), OPR, right.ex_flt);\ + for (j = 0; j < expr->exp_vsize; j++) \ + *op++ = scalar; \ + } else { \ + optr->ex_type = ET_FLT; \ + optr->ex_flt = DZC(((t_float)left.ex_int), OPR, \ + right.ex_flt); \ + } \ + break; \ + case ET_VEC: \ + case ET_VI: \ + if (optr->ex_type != ET_VEC) { \ + if (optr->ex_type == ET_VI) { \ + post("expr~: Int. error %d", __LINE__); \ + abort(); \ + } \ + optr->ex_type = ET_VEC; \ + optr->ex_vec = (t_float *) \ + fts_malloc(sizeof (t_float)*expr->exp_vsize); \ + } \ + scalar = left.ex_int; \ + rp = right.ex_vec; \ + op = optr->ex_vec; \ + for (i = 0; i < expr->exp_vsize; i++) { \ + *op++ = DZC (scalar, OPR, *rp); \ + rp++; \ + } \ + break; \ + case ET_SYM: \ + default: \ + post_error((fts_object_t *) expr, \ + "expr: ex_eval(%d): bad right type %ld\n", \ + __LINE__, right.ex_type); \ + nullret = 1; \ + } \ + break; \ +case ET_FLT: \ + switch(right.ex_type) { \ + case ET_INT: \ + if (optr->ex_type == ET_VEC) { \ + op = optr->ex_vec; \ + scalar = DZC((t_float) left.ex_flt, OPR, right.ex_int); \ + for (j = 0; j < expr->exp_vsize; j++) \ + *op++ = scalar; \ + } else { \ + optr->ex_type = ET_FLT; \ + optr->ex_flt = DZC(left.ex_flt, OPR, right.ex_int); \ + } \ + break; \ + case ET_FLT: \ + if (optr->ex_type == ET_VEC) { \ + op = optr->ex_vec; \ + scalar = DZC(left.ex_flt, OPR, right.ex_flt); \ + for (j = 0; j < expr->exp_vsize; j++) \ + *op++ = scalar; \ + } else { \ + optr->ex_type = ET_FLT; \ + optr->ex_flt= DZC(left.ex_flt, OPR, right.ex_flt); \ + } \ + break; \ + case ET_VEC: \ + case ET_VI: \ + if (optr->ex_type != ET_VEC) { \ + if (optr->ex_type == ET_VI) { \ + post("expr~: Int. error %d", __LINE__); \ + abort(); \ + } \ + optr->ex_type = ET_VEC; \ + optr->ex_vec = (t_float *) \ + fts_malloc(sizeof (t_float)*expr->exp_vsize); \ + } \ + scalar = left.ex_flt; \ + rp = right.ex_vec; \ + op = optr->ex_vec; \ + for (i = 0; i < expr->exp_vsize; i++) { \ + *op++ = DZC(scalar, OPR, *rp); \ + rp++; \ + } \ + break; \ + case ET_SYM: \ + default: \ + post_error((fts_object_t *) expr, \ + "expr: ex_eval(%d): bad right type %ld\n", \ + __LINE__, right.ex_type); \ + nullret = 1; \ + } \ + break; \ +case ET_VEC: \ +case ET_VI: \ + if (optr->ex_type != ET_VEC) { \ + if (optr->ex_type == ET_VI) { \ + post("expr~: Int. error %d", __LINE__); \ + abort(); \ + } \ + optr->ex_type = ET_VEC; \ + optr->ex_vec = (t_float *) \ + fts_malloc(sizeof (t_float)*expr->exp_vsize); \ + } \ + op = optr->ex_vec; \ + lp = left.ex_vec; \ + switch(right.ex_type) { \ + case ET_INT: \ + scalar = right.ex_int; \ + for (i = 0; i < expr->exp_vsize; i++) { \ + *op++ = DZC(*lp, OPR, scalar); \ + lp++; \ + } \ + break; \ + case ET_FLT: \ + scalar = right.ex_flt; \ + for (i = 0; i < expr->exp_vsize; i++) { \ + *op++ = DZC(*lp, OPR, scalar); \ + lp++; \ + } \ + break; \ + case ET_VEC: \ + case ET_VI: \ + rp = right.ex_vec; \ + for (i = 0; i < expr->exp_vsize; i++) { \ + /* \ + * on a RISC processor one could copy \ + * 8 times in each round to get a considerable \ + * improvement \ + */ \ + *op++ = DZC(*lp, OPR, *rp); \ + rp++; lp++; \ + } \ + break; \ + case ET_SYM: \ + default: \ + post_error((fts_object_t *) expr, \ + "expr: ex_eval(%d): bad right type %ld\n", \ + __LINE__, right.ex_type); \ + nullret = 1; \ + } \ + break; \ +case ET_SYM: \ +default: \ + post_error((fts_object_t *) expr, \ + "expr: ex_eval(%d): bad left type %ld\n", \ + __LINE__, left.ex_type); \ +} \ +break; + +/* + * evaluate a unary operator, TYPE is applied to float operands + */ +#define EVAL_UNARY(OPR, TYPE) \ + eptr = ex_eval(expr, eptr, &left, idx); \ + switch(left.ex_type) { \ + case ET_INT: \ + if (optr->ex_type == ET_VEC) { \ + ex_mkvector(optr->ex_vec,(t_float)(OPR left.ex_int),\ + expr->exp_vsize);\ + break; \ + } \ + optr->ex_type = ET_INT; \ + optr->ex_int = OPR left.ex_int; \ + break; \ + case ET_FLT: \ + if (optr->ex_type == ET_VEC) { \ + ex_mkvector(optr->ex_vec, OPR (TYPE left.ex_flt),\ + expr->exp_vsize);\ + break; \ + } \ + optr->ex_type = ET_FLT; \ + optr->ex_flt = OPR (TYPE left.ex_flt); \ + break; \ + case ET_VI: \ + case ET_VEC: \ + j = expr->exp_vsize; \ + if (optr->ex_type != ET_VEC) { \ + optr->ex_type = ET_VEC; \ + optr->ex_vec = (t_float *) \ + fts_malloc(sizeof (t_float)*expr->exp_vsize); \ + } \ + op = optr->ex_vec; \ + lp = left.ex_vec; \ + j = expr->exp_vsize; \ + for (i = 0; i < j; i++) \ + *op++ = OPR (TYPE *lp++); \ + break; \ + default: \ + post_error((fts_object_t *) expr, \ + "expr: ex_eval(%d): bad left type %ld\n", \ + __LINE__, left.ex_type); \ + nullret++; \ + } \ + break; + +void +ex_mkvector(t_float *fp, t_float x, int size) +{ + while (size--) + *fp++ = x; +} + +/* + * ex_dzdetect -- divide by zero detected + */ +void +ex_dzdetect(struct expr *expr) +{ + char *etype; + + if ((!expr->exp_error) & EE_DZ) { + if (IS_EXPR(expr)) + etype = "expr"; + else if (IS_EXPR_TILDE(expr)) + etype = "expr~"; + else if (IS_FEXPR_TILDE(expr)) + etype = "fexpr~"; + else { + post ("expr -- ex_dzdetect internal error"); + etype = ""; + } + post ("%s divide by zero detected", etype); + expr->exp_error |= EE_DZ; + } +} + + +/* + * ex_eval -- evaluate the array of prefix expression + * ex_eval returns the pointer to the first unevaluated node + * in the array. This is a recursive routine. + */ + +/* SDY - potential memory leak +all the returns in this function need to be changed so that the code +ends up at the end to check for newly allocated right and left vectors which +need to be freed + +look into the variable nullret +*/ +struct ex_ex * +ex_eval(struct expr *expr, struct ex_ex *eptr, struct ex_ex *optr, int idx) +/* the expr object data pointer */ +/* the operation stack */ +/* the result pointer */ +/* the sample numnber processed for fexpr~ */ +{ + int i, j; + t_float *lp, *rp, *op; /* left, right, and out pointer to vectors */ + t_float scalar; + int nullret = 0; /* did we have an error */ + struct ex_ex left, right; /* left and right operands */ + + left.ex_type = 0; + left.ex_int = 0; + right.ex_type = 0; + right.ex_int = 0; + + if (!eptr) + return (exNULL); + switch (eptr->ex_type) { + case ET_INT: + if (optr->ex_type == ET_VEC) + ex_mkvector(optr->ex_vec, (t_float) eptr->ex_int, + expr->exp_vsize); + else + *optr = *eptr; + return (++eptr); + + case ET_FLT: + + if (optr->ex_type == ET_VEC) + ex_mkvector(optr->ex_vec, eptr->ex_flt, expr->exp_vsize); + else + *optr = *eptr; + return (++eptr); + + case ET_SYM: + if (optr->ex_type == ET_VEC) { + post_error((fts_object_t *) expr, + "expr: ex_eval: cannot turn string to vector\n"); + return (exNULL); + } + *optr = *eptr; + return (++eptr); + case ET_II: + if (eptr->ex_int == -1) { + post_error((fts_object_t *) expr, + "expr: ex_eval: inlet number not set\n"); + return (exNULL); + } + if (optr->ex_type == ET_VEC) { + ex_mkvector(optr->ex_vec, + (t_float)expr->exp_var[eptr->ex_int].ex_int, + expr->exp_vsize); + } else { + optr->ex_type = ET_INT; + optr->ex_int = expr->exp_var[eptr->ex_int].ex_int; + } + return (++eptr); + case ET_FI: + if (eptr->ex_int == -1) { + post_error((fts_object_t *) expr, + "expr: ex_eval: inlet number not set\n"); + return (exNULL); + } + if (optr->ex_type == ET_VEC) { + ex_mkvector(optr->ex_vec, + expr->exp_var[eptr->ex_int].ex_flt, expr->exp_vsize); + } else { + optr->ex_type = ET_FLT; + optr->ex_flt = expr->exp_var[eptr->ex_int].ex_flt; + } + return (++eptr); + + case ET_VSYM: + if (optr->ex_type == ET_VEC) { + post_error((fts_object_t *) expr, + "expr: IntErr. vsym in for vec out\n"); + return (exNULL); + } + if (eptr->ex_int == -1) { + post_error((fts_object_t *) expr, + "expr: ex_eval: inlet number not set\n"); + return (exNULL); + } + optr->ex_type = ET_SYM; + optr->ex_ptr = expr->exp_var[eptr->ex_int].ex_ptr; + return(++eptr); + + case ET_VI: + if (optr->ex_type != ET_VEC) + *optr = expr->exp_var[eptr->ex_int]; + else if (optr->ex_vec != expr->exp_var[eptr->ex_int].ex_vec) + memcpy(optr->ex_vec, expr->exp_var[eptr->ex_int].ex_vec, + expr->exp_vsize * sizeof (t_float)); + return(++eptr); + case ET_VEC: + if (optr->ex_type != ET_VEC) { + optr->ex_type = ET_VEC; + optr->ex_vec = eptr->ex_vec; + eptr->ex_type = ET_INT; + eptr->ex_int = 0; + } else if (optr->ex_vec != eptr->ex_vec) { + memcpy(optr->ex_vec, eptr->ex_vec, + expr->exp_vsize * sizeof (t_float)); + fts_free(eptr->ex_vec); + } else { /* this should not happen */ + post("expr int. error, optr->ex_vec = %d",optr->ex_vec); + abort(); + } + return(++eptr); + case ET_XI0: + /* short hand for $x?[0] */ + + /* SDY delete the following check */ + if (!IS_FEXPR_TILDE(expr) || optr->ex_type==ET_VEC) { + post("%d:exp->exp_flags = %d", __LINE__,expr->exp_flags); + abort(); + } + optr->ex_type = ET_FLT; + optr->ex_flt = expr->exp_var[eptr->ex_int].ex_vec[idx]; + return(++eptr); + case ET_YOM1: + /* + * short hand for $y?[-1] + * if we are calculating the first sample of the vector + * we need to look at the previous results buffer + */ + optr->ex_type = ET_FLT; + if (idx == 0) + optr->ex_flt = + expr->exp_p_res[eptr->ex_int][expr->exp_vsize - 1]; + else + optr->ex_flt=expr->exp_tmpres[eptr->ex_int][idx-1]; + return(++eptr); + + case ET_YO: + case ET_XI: + /* SDY delete the following */ + if (!IS_FEXPR_TILDE(expr) || optr->ex_type==ET_VEC) { + post("%d:expr->exp_flags = %d", __LINE__,expr->exp_flags); + abort(); + } + return (eval_sigidx(expr, eptr, optr, idx)); + + case ET_TBL: + case ET_SI: + return (eval_tab(expr, eptr, optr, idx)); + case ET_FUNC: + return (eval_func(expr, eptr, optr, idx)); + case ET_VAR: + return (eval_var(expr, eptr, optr, idx)); + case ET_OP: + break; + case ET_STR: + case ET_LP: + case ET_LB: + default: + post_error((fts_object_t *) expr, + "expr: ex_eval: unexpected type %d\n", + (int)eptr->ex_type); + return (exNULL); + } + if (!eptr[1].ex_type) { + post_error((fts_object_t *) expr, + "expr: ex_eval: not enough nodes 1\n"); + return (exNULL); + } + if (!unary_op(eptr->ex_op) && !eptr[2].ex_type) { + post_error((fts_object_t *) expr, + "expr: ex_eval: not enough nodes 2\n"); + return (exNULL); + } + + switch((eptr++)->ex_op) { + case OP_STORE: + return (eval_store(expr, eptr, optr, idx)); + case OP_NOT: + EVAL_UNARY(!, +); + case OP_NEG: + EVAL_UNARY(~, (long)); + case OP_UMINUS: + EVAL_UNARY(-, +); + case OP_MUL: + EVAL(*); + case OP_ADD: + EVAL(+); + case OP_SUB: + EVAL(-); + case OP_LT: + EVAL(<); + case OP_LE: + EVAL(<=); + case OP_GT: + EVAL(>); + case OP_GE: + EVAL(>=); + case OP_EQ: + EVAL(==); + case OP_NE: + EVAL(!=); +/* + * following operators convert their argument to integer + */ +#undef DZC +#define DZC(ARG1,OPR,ARG2) (((int)ARG1) OPR ((int)ARG2)) + case OP_SL: + EVAL(<<); + case OP_SR: + EVAL(>>); + case OP_AND: + EVAL(&); + case OP_XOR: + EVAL(^); + case OP_OR: + EVAL(|); + case OP_LAND: + EVAL(&&); + case OP_LOR: + EVAL(||); +/* + * for modulo we need to convert to integer and check for divide by zero + */ +#undef DZC +#define DZC(ARG1,OPR,ARG2) ((((int)ARG2)?(((int)ARG1) OPR ((int)ARG2)) \ + : (ex_dzdetect(expr),0))) + case OP_MOD: + EVAL(%); +/* + * define the divide by zero check for divide + */ +#undef DZC +#define DZC(ARG1,OPR,ARG2) (((ARG2)?(ARG1 OPR ARG2):(ex_dzdetect(expr),0))) + case OP_DIV: + EVAL(/); + case OP_LP: + case OP_RP: + case OP_LB: + case OP_RB: + case OP_COMMA: + case OP_SEMI: + default: + post_error((fts_object_t *) expr, + "expr: ex_print: bad op 0x%x\n", (unsigned)eptr->ex_op); + return (exNULL); + } + + + /* + * the left and right nodes could have been transformed to vectors + * down the chain + */ + if (left.ex_type == ET_VEC) + fts_free(left.ex_vec); + if (right.ex_type == ET_VEC) + fts_free(right.ex_vec); + if (nullret) + return (exNULL); + else + return (eptr); +} + +extern struct ex_ex * ex_if(t_expr *expr, struct ex_ex *eptr, + struct ex_ex *optr,struct ex_ex *argv, int idx); + +/* + * eval_func -- evaluate a function, call ex_eval() on all the arguments + * so that all of them are terminal nodes. The call the + * appropriate function + */ +struct ex_ex * +eval_func(struct expr *expr, struct ex_ex *eptr, struct ex_ex *optr, int idx) +/* the expr object data pointer */ +/* the operation stack */ +/* the result pointer */ +{ + int i; + struct ex_ex args[MAX_ARGS]; + t_ex_func *f; + + f = (t_ex_func *)(eptr++)->ex_ptr; + if (!f || !f->f_name) { + return (exNULL); + } + if (f->f_argc > MAX_ARGS) { + post_error((fts_object_t *) expr, "expr: eval_func: asking too many arguments\n"); + return (exNULL); + } + + /* + * We treat the "if" function differently to be able to evaluate + * the args selectively based on the truth value of the "condition" + */ + if (f->f_func != (void (*)) ex_if) { + for (i = 0; i < f->f_argc; i++) { + args[i].ex_type = 0; + args[i].ex_int = 0; + eptr = ex_eval(expr, eptr, &args[i], idx); + } + (*f->f_func)(expr, f->f_argc, args, optr); + } else { + for (i = 0; i < f->f_argc; i++) { + args[i].ex_type = 0; + args[i].ex_int = 0; + } + eptr = ex_if(expr, eptr, optr, args, idx); + } + for (i = 0; i < f->f_argc; i++) { + if (args[i].ex_type == ET_VEC) + fts_free(args[i].ex_vec); + } + return (eptr); +} + + +/* + * eval_store -- evaluate the '=' operator, + * make sure the first operator is a legal left operator + * and call ex_eval on the right operator + */ +struct ex_ex * +eval_store(struct expr *expr, struct ex_ex *eptr, struct ex_ex *optr, int idx) +/* the expr object data pointer */ +/* the operation stack */ +/* the result pointer */ +{ + struct ex_ex arg; + struct ex_ex rval; + struct ex_ex *retp; + int isvalue; + char *tbl = (char *) 0; + char *var = (char *) 0; + int badleft = 0; + int notable = 0; + + switch (eptr->ex_type) { + case ET_VAR: + var = (char *) eptr->ex_ptr; + eptr = ex_eval(expr, ++eptr, &arg, idx); + if (max_ex_var_store(expr, (t_symbol *)var, &arg, optr)) + retp = exNULL; + else + retp = eptr; + + if (arg.ex_type == ET_VEC) + fts_free(arg.ex_vec); + return(retp); + case ET_TBL: + tbl = (char *) eptr->ex_ptr; + break; + case ET_SI: + if (!expr->exp_var[eptr->ex_int].ex_ptr) { + if (!(expr->exp_error & EE_NOTABLE)) { + post("expr: syntax error: no string for inlet %d", + eptr->ex_int + 1); + post("expr: No more table errors will be reported"); + post("expr: till the next reset"); + expr->exp_error |= EE_NOTABLE; + } + badleft++; + post("Bad left value: "); + /* report Error */ + ex_print(eptr); + retp = exNULL; + return (retp); + } else { + tbl = (char *) expr->exp_var[eptr->ex_int].ex_ptr; + } + break; + default: + post("Bad left value: "); + /* report Error */ + ex_print(eptr); + retp = exNULL; + return (retp); + } + arg.ex_type = 0; + arg.ex_int = 0; + /* evaluate the index of the table */ + if (!(eptr = ex_eval(expr, ++eptr, &arg, idx))) + return (eptr); + + /* evaluate the right index of the table */ + if (!(eptr = ex_eval(expr, eptr, &rval, idx))) + return (eptr); + optr->ex_type = ET_INT; + optr->ex_int = 0; + if (!notable || badleft) + (void)max_ex_tab_store(expr, (t_symbol *)tbl, &arg, &rval, optr); + if (arg.ex_type == ET_VEC) + fts_free(arg.ex_vec); + return (eptr); +} + +/* + * eval_tab -- evaluate a table operation + */ +struct ex_ex * +eval_tab(struct expr *expr, struct ex_ex *eptr, struct ex_ex *optr, int idx) +/* the expr object data pointer */ +/* the operation stack */ +/* the result pointer */ +{ + struct ex_ex arg; + char *tbl = (char *) 0; + int notable = 0; + + if (eptr->ex_type == ET_SI) { + if (!expr->exp_var[eptr->ex_int].ex_ptr) { + if (!(expr->exp_error & EE_NOTABLE)) { + post("expr: syntax error: no string for inlet %d", + eptr->ex_int + 1); + post("expr: No more table errors will be reported"); + post("expr: till the next reset"); + expr->exp_error |= EE_NOTABLE; + } + notable++; + } else + tbl = (char *) expr->exp_var[eptr->ex_int].ex_ptr; + } else if (eptr->ex_type == ET_TBL) { + tbl = (char *) eptr->ex_ptr; + if (!tbl) { + post("expr: abstraction argument for table not set"); + notable++; + } + + } else { + post_error((fts_object_t *) expr,"expr: eval_tbl: bad type %ld\n",eptr->ex_type); + notable++; + + } + arg.ex_type = 0; + arg.ex_int = 0; + if (!(eptr = ex_eval(expr, ++eptr, &arg, idx))) + return (eptr); + + optr->ex_type = ET_INT; + optr->ex_int = 0; + if (!notable) + (void)max_ex_tab(expr, (t_symbol *)tbl, &arg, optr); + if (arg.ex_type == ET_VEC) + fts_free(arg.ex_vec); + return (eptr); +} + +/* + * eval_var -- evaluate a variable + */ +struct ex_ex * +eval_var(struct expr *expr, struct ex_ex *eptr, struct ex_ex *optr, int idx) +/* the expr object data pointer */ +/* the operation stack */ +/* the result pointer */ +{ + struct ex_ex arg; + char *var = (char *) 0; + int novar = 0; + + if (eptr->ex_type == ET_SI) { + if (!expr->exp_var[eptr->ex_int].ex_ptr) { + if (!(expr->exp_error & EE_NOVAR)) { + post("expr: syntax error: no string for inlet %d", eptr->ex_int + 1); + post("expr: No more table errors will be reported"); + post("expr: till the next reset"); + expr->exp_error |= EE_NOVAR; + } + novar++; + } else + var = (char *) expr->exp_var[eptr->ex_int].ex_ptr; + } else if (eptr->ex_type == ET_VAR) + var = (char *) eptr->ex_ptr; + else { + post_error((fts_object_t *) expr, "expr: eval_tbl: bad type %ld\n", eptr->ex_type); + novar++; + + } + + optr->ex_type = ET_INT; + optr->ex_int = 0; + if (!novar) + (void)max_ex_var(expr, (t_symbol *)var, optr, idx); + return (++eptr); +} + +/* + * eval_sigidx -- evaluate the value of an indexed signal for fexpr~ + */ +struct ex_ex * +eval_sigidx(struct expr *expr, struct ex_ex *eptr, struct ex_ex *optr, int idx) +/* the expr object data pointer */ +/* the operation stack */ +/* the result pointer */ +/* the index */ +{ + struct ex_ex arg; + struct ex_ex *reteptr; + int i = 0, j = 0; + t_float fi = 0, /* index in float */ + rem_i = 0; /* remains of the float */ + char *tbl; + + arg.ex_type = 0; + arg.ex_int = 0; + reteptr = ex_eval(expr, eptr + 1, &arg, idx); + if (arg.ex_type == ET_FLT) { + fi = arg.ex_flt; /* float index */ + i = (int) arg.ex_flt; /* integer index */ + rem_i = arg.ex_flt - i; /* remains of integer */ + } else if (arg.ex_type == ET_INT) { + fi = arg.ex_int; /* float index */ + i = (int) arg.ex_int; /* integer index */ + rem_i = 0; + } else { + post("eval_sigidx: bad res type (%d)", arg.ex_type); + } + optr->ex_type = ET_FLT; + /* + * indexing an input vector + */ + if (eptr->ex_type == ET_XI) { + if (fi > 0) { + if (!(expr->exp_error & EE_BI_INPUT)) { + expr->exp_error |= EE_BI_INPUT; + post("expr: input vector index > 0, (vector x%d[%f])", + eptr->ex_int + 1, i + rem_i); + post("fexpr~: index assumed to be = 0"); + post("fexpr~: no error report till next reset"); + ex_print(eptr); + } + /* just replace it with zero */ + i = 0; + rem_i = 0; + } + if (cal_sigidx(optr, i, rem_i, idx, expr->exp_vsize, + expr->exp_var[eptr->ex_int].ex_vec, + expr->exp_p_var[eptr->ex_int])) { + if (!(expr->exp_error & EE_BI_INPUT)) { + expr->exp_error |= EE_BI_INPUT; + post("expr: input vector index < -VectorSize, (vector x%d[%f])", eptr->ex_int + 1, fi); + ex_print(eptr); + post("fexpr~: index assumed to be = -%d", + expr->exp_vsize); + post("fexpr~: no error report till next reset"); + } + } + + /* + * indexing an output vector + */ + } else if (eptr->ex_type == ET_YO) { + /* for output vectors index of zero is not legal */ + if (fi >= 0) { + if (!(expr->exp_error & EE_BI_OUTPUT)) { + expr->exp_error |= EE_BI_OUTPUT; + post("fexpr~: bad output index, (%f)", fi); + ex_print(eptr); + post("fexpr~: no error report till next reset"); + post("fexpr~: index assumed to be = -1"); + } + i = -1; + } + if (eptr->ex_int >= expr->exp_nexpr) { + post("fexpr~: $y%d illegal: not that many exprs", + eptr->ex_int); + optr->ex_flt = 0; + return (reteptr); + } + if (cal_sigidx(optr, i, rem_i, idx, expr->exp_vsize, + expr->exp_tmpres[eptr->ex_int], + expr->exp_p_res[eptr->ex_int])) { + if (!(expr->exp_error & EE_BI_OUTPUT)) { + expr->exp_error |= EE_BI_OUTPUT; + post("fexpr~: bad output index, (%f)", fi); + ex_print(eptr); + post("fexpr~: index assumed to be = -%d", + expr->exp_vsize); + } + } + } else { + optr->ex_flt = 0; + post("fexpr~:eval_sigidx: internal error - unknown vector (%d)", + eptr->ex_type); + } + return (reteptr); +} + +/* + * cal_sigidx -- given two tables (one current one previous) calculate an + * evaluation of a float index into the vectors by linear + * interpolation + * return 0 on success, 1 on failure (index out of bound) + */ +static int +cal_sigidx(struct ex_ex *optr, /* The output value */ + int i, t_float rem_i,/* integer and fractinal part of index */ + int idx, /* index of current fexpr~ processing */ + int vsize, /* vector size */ + t_float *curvec, t_float *prevec) /* current and previous table */ +{ + int n; + + n = i + idx; + if (n > 0) { + /* from the curvec */ + if (rem_i) + optr->ex_flt = curvec[n] + + rem_i * (curvec[n] - curvec[n - 1]); + else + optr->ex_flt = curvec[n]; + return (0); + } + if (n == 0) { + /* + * this is the case that the remaining float + * is between two tables + */ + if (rem_i) + optr->ex_flt = *curvec + + rem_i * (*curvec - prevec[vsize - 1]); + else + optr->ex_flt = *curvec; + return (0); + } + /* find the index in the saved buffer */ + n = vsize + n; + if (n > 0) { + if (rem_i) + optr->ex_flt = prevec[n] + + rem_i * (prevec[n] - prevec[n - 1]); + else + optr->ex_flt = prevec[n]; + return (0); + } + /* out of bound */ + optr->ex_flt = *prevec; + return (1); +} + +/* + * getoken -- return 1 on syntax error otherwise 0 + */ +int +getoken(struct expr *expr, struct ex_ex *eptr) +{ + char *p; + long i; + + + if (!expr->exp_str) { + post("expr: getoken: expression string not set\n"); + return (0); + } +retry: + if (!*expr->exp_str) { + eptr->ex_type = 0; + eptr->ex_int = 0; + return (0); + } + if (*expr->exp_str == ';') { + expr->exp_str++; + eptr->ex_type = 0; + eptr->ex_int = 0; + return (0); + } + eptr->ex_type = ET_OP; + switch (*expr->exp_str++) { + case '\\': + case ' ': + case '\t': + goto retry; + case ';': + post("expr: syntax error: ';' not implemented\n"); + return (1); + case ',': + eptr->ex_op = OP_COMMA; + break; + case '(': + eptr->ex_op = OP_LP; + break; + case ')': + eptr->ex_op = OP_RP; + break; + case ']': + eptr->ex_op = OP_RB; + break; + case '~': + eptr->ex_op = OP_NEG; + break; + /* we will take care of unary minus later */ + case '*': + eptr->ex_op = OP_MUL; + break; + case '/': + eptr->ex_op = OP_DIV; + break; + case '%': + eptr->ex_op = OP_MOD; + break; + case '+': + eptr->ex_op = OP_ADD; + break; + case '-': + eptr->ex_op = OP_SUB; + break; + case '^': + eptr->ex_op = OP_XOR; + break; + case '[': + eptr->ex_op = OP_LB; + break; + case '!': + if (*expr->exp_str == '=') { + eptr->ex_op = OP_NE; + expr->exp_str++; + } else + eptr->ex_op = OP_NOT; + break; + case '<': + switch (*expr->exp_str) { + case '<': + eptr->ex_op = OP_SL; + expr->exp_str++; + break; + case '=': + eptr->ex_op = OP_LE; + expr->exp_str++; + break; + default: + eptr->ex_op = OP_LT; + break; + } + break; + case '>': + switch (*expr->exp_str) { + case '>': + eptr->ex_op = OP_SR; + expr->exp_str++; + break; + case '=': + eptr->ex_op = OP_GE; + expr->exp_str++; + break; + default: + eptr->ex_op = OP_GT; + break; + } + break; + case '=': + if (*expr->exp_str != '=') + eptr->ex_op = OP_STORE; + else { + expr->exp_str++; + eptr->ex_op = OP_EQ; + } + break; + + case '&': + if (*expr->exp_str == '&') { + expr->exp_str++; + eptr->ex_op = OP_LAND; + } else + eptr->ex_op = OP_AND; + break; + + case '|': + if (*expr->exp_str == '|') { + expr->exp_str++; + eptr->ex_op = OP_LOR; + } else + eptr->ex_op = OP_OR; + break; + case '$': + switch (*expr->exp_str++) { + case 'I': + case 'i': + eptr->ex_type = ET_II; + break; + case 'F': + case 'f': + eptr->ex_type = ET_FI; + break; + case 'S': + case 's': + eptr->ex_type = ET_SI; + break; + case 'V': + case 'v': + if (IS_EXPR_TILDE(expr)) { + eptr->ex_type = ET_VI; + break; + } + post("$v? works only for expr~"); + post("expr: syntax error: %s\n", &expr->exp_str[-2]); + return (1); + case 'X': + case 'x': + if (IS_FEXPR_TILDE(expr)) { + eptr->ex_type = ET_XI; + if (isdigit(*expr->exp_str)) + break; + /* for $x[] is a shorhand for $x1[] */ + /* eptr->ex_int = 0; */ + eptr->ex_op = 0; + expr->exp_var[eptr->ex_op].ex_type = eptr->ex_type; + goto noinletnum; + } + post("$x? works only for fexpr~"); + post("expr: syntax error: %s\n", &expr->exp_str[-2]); + return (1); + case 'y': + case 'Y': + if (IS_FEXPR_TILDE(expr)) { + eptr->ex_type = ET_YO; + /*$y takes no number */ + if (isdigit(*expr->exp_str)) + break; + /* for $y[] is a shorhand for $y1[] */ + /* eptr->ex_int = 0; */ + eptr->ex_op = 0; + expr->exp_var[eptr->ex_op].ex_type = eptr->ex_type; + goto noinletnum; + } + post("$y works only for fexpr~"); + /* falls through */ + /* + * allow $# for abstration argument substitution + * $1+1 is translated to 0+1 and in abstration substitution + * the value is replaced with the new string + */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + p = atoif(--expr->exp_str, &eptr->ex_op, &i); + if (!p) + return (1); + if (i != ET_INT) { + post("expr: syntax error: %s\n", expr->exp_str); + return (1); + } + expr->exp_str = p; + eptr->ex_type = ET_INT; + eptr->ex_int = 0; + return (0); + default: + post("expr: syntax error: %s\n", &expr->exp_str[-2]); + return (1); + } + p = atoif(expr->exp_str, &eptr->ex_op, &i); + if (!p) { + post("expr: syntax error: %s\n", &expr->exp_str[-2]); + return (1); + } + if (i != ET_INT) { + post("expr: syntax error: %s\n", expr->exp_str); + return (1); + } + /* + * make the user inlets one based rather than zero based + * therefore we decrement the number that user has supplied + */ + if (!eptr->ex_op || (eptr->ex_op)-- > MAX_VARS) { + post("expr: syntax error: inlet or outlet out of range: %s\n", + expr->exp_str); + return (1); + } + + /* + * until we can change the input type of inlets on + * the fly (at pd_new() + * time) the first input to expr~ is always a vectore + * and $f1 or $i1 is + * illegal for fexpr~ + */ + if (eptr->ex_op == 0 && + (IS_FEXPR_TILDE(expr) || IS_EXPR_TILDE(expr)) && + (eptr->ex_type==ET_II || eptr->ex_type==ET_FI || + eptr->ex_type==ET_SI)) { + post("first inlet of expr~/fexpr~ can only be a vector"); + return (1); + } + /* record the inlet or outlet type and check for consistency */ + if (eptr->ex_type == ET_YO ) { + /* it is an outlet for fexpr~*/ + /* no need to do anything */ + ; + } else if (!expr->exp_var[eptr->ex_op].ex_type) + expr->exp_var[eptr->ex_op].ex_type = eptr->ex_type; + else if (expr->exp_var[eptr->ex_op].ex_type != eptr->ex_type) { + post("expr: syntax error: inlets can only have one type: %s\n", expr->exp_str); + return (1); + } + expr->exp_str = p; +noinletnum: + break; + case '"': + { + struct ex_ex ex; + + p = expr->exp_str; + if (!*expr->exp_str || *expr->exp_str == '"') { + post("expr: syntax error: empty symbol: %s\n", --expr->exp_str); + return (1); + } + if (getoken(expr, &ex)) + return (1); + switch (ex.ex_type) { + case ET_STR: + if (ex_getsym(ex.ex_ptr, (t_symbol **)&(eptr->ex_ptr))) { + post("expr: syntax error: getoken: problms with ex_getsym\n"); + return (1); + } + eptr->ex_type = ET_SYM; + break; + case ET_SI: + *eptr = ex; + eptr->ex_type = ET_VSYM; + break; + default: + post("expr: syntax error: bad symbol name: %s\n", p); + return (1); + } + if (*expr->exp_str++ != '"') { + post("expr: syntax error: missing '\"'\n"); + return (1); + } + break; + } + case '.': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + p = atoif(--expr->exp_str, &eptr->ex_int, &eptr->ex_type); + if (!p) + return (1); + expr->exp_str = p; + break; + + default: + /* + * has to be a string, it should either be a + * function or a table + */ + p = --expr->exp_str; + for (i = 0; name_ok(*p); i++) + p++; + if (!i) { + post("expr: syntax error: %s\n", expr->exp_str); + return (1); + } + eptr->ex_ptr = (char *)fts_malloc(i + 1); + strncpy(eptr->ex_ptr, expr->exp_str, (int) i); + (eptr->ex_ptr)[i] = 0; + expr->exp_str = p; + /* + * we mark this as a string and later we will change this + * to either a function or a table + */ + eptr->ex_type = ET_STR; + break; + } + return (0); +} + +/* + * atoif -- ascii to float or integer (strtof() understand exponential notations ad strtod() understand hex numbers) + */ +char * +atoif(char *s, long int *value, long int *type) +{ + char *p; + long lval; + float fval; + + lval = strtod(s, &p); + fval = strtof(s, &p); + if (lval != (int) fval) { + *type = ET_FLT; + *((t_float *) value) = fval; + return (p); + } + while (s != p) { + if (*s == 'x' || *s == 'X') + break; + if (*s == '.' || *s == 'e' || *s == 'E') { + *type = ET_FLT; + *((t_float *) value) = fval; + return (p); + } + s++; + } + *type = ET_INT; + *((t_int *) value) = lval; + return (p); +} + +/* + * find_func -- returns a pointer to the found function structure + * otherwise it returns 0 + */ +t_ex_func * +find_func(char *s) +{ + t_ex_func *f; + + for (f = ex_funcs; f->f_name; f++) + if (!strcmp(f->f_name, s)) + return (f); + return ((t_ex_func *) 0); +} + + +/* + * ex_print -- print an expression array + */ + +void +ex_print(struct ex_ex *eptr) +{ + struct ex_ex *extmp; + + extmp = eptr->ex_end; + while (eptr->ex_type && eptr != extmp) { + switch (eptr->ex_type) { + case ET_INT: + post("%ld ", eptr->ex_int); + break; + case ET_FLT: + post("%f ", eptr->ex_flt); + break; + case ET_STR: + post("%s ", eptr->ex_ptr); + break; + case ET_TBL: + if (!eptr->ex_ptr) { /* special case of $# processing */ + post("%s ", "$$"); + break; + } + /* falls through */ + case ET_VAR: + post("%s ", ex_symname((fts_symbol_t )eptr->ex_ptr)); + break; + case ET_SYM: + post("\"%s\" ", ex_symname((fts_symbol_t )eptr->ex_ptr)); + break; + case ET_VSYM: + post("\"$s%ld\" ", eptr->ex_int + 1); + break; + case ET_FUNC: + post("%s ", + ((t_ex_func *)eptr->ex_ptr)->f_name); + break; + case ET_LP: + post("%c", '('); + break; + /* CHANGE + case ET_RP: + post("%c ", ')'); + break; + */ + case ET_LB: + post("%c", '['); + break; + /* CHANGE + case ET_RB: + post("%c ", ']'); + break; + */ + case ET_II: + post("$i%ld ", eptr->ex_int + 1); + break; + case ET_FI: + post("$f%ld ", eptr->ex_int + 1); + break; + case ET_SI: + post("$s%lx ", eptr->ex_ptr); + break; + case ET_VI: + post("$v%lx ", eptr->ex_vec); + break; + case ET_VEC: + post("vec = %ld ", eptr->ex_vec); + break; + case ET_YOM1: + case ET_YO: + post("$y%d", eptr->ex_int + 1); + break; + case ET_XI: + case ET_XI0: + post("$x%d", eptr->ex_int + 1); + break; + case ET_OP: + switch (eptr->ex_op) { + case OP_LP: + post("%c", '('); + break; + case OP_RP: + post("%c ", ')'); + break; + case OP_LB: + post("%c", '['); + break; + case OP_RB: + post("%c ", ']'); + break; + case OP_NOT: + post("%c", '!'); + break; + case OP_NEG: + post("%c", '~'); + break; + case OP_UMINUS: + post("%c", '-'); + break; + case OP_MUL: + post("%c", '*'); + break; + case OP_DIV: + post("%c", '/'); + break; + case OP_MOD: + post("%c", '%'); + break; + case OP_ADD: + post("%c", '+'); + break; + case OP_SUB: + post("%c", '-'); + break; + case OP_SL: + post("%s", "<<"); + break; + case OP_SR: + post("%s", ">>"); + break; + case OP_LT: + post("%c", '<'); + break; + case OP_LE: + post("%s", "<="); + break; + case OP_GT: + post("%c", '>'); + break; + case OP_GE: + post("%s", ">="); + break; + case OP_EQ: + post("%s", "=="); + break; + case OP_STORE: + post("%s", "="); + break; + case OP_NE: + post("%s", "!="); + break; + case OP_AND: + post("%c", '&'); + break; + case OP_XOR: + post("%c", '^'); + break; + case OP_OR: + post("%c", '|'); + break; + case OP_LAND: + post("%s", "&&"); + break; + case OP_LOR: + post("%s", "||"); + break; + case OP_COMMA: + post("%c", ','); + break; + case OP_SEMI: + post("%c", ';'); + break; + default: + post("expr: ex_print: bad op 0x%lx\n", eptr->ex_op); + } + break; + default: + post("expr: ex_print: bad type 0x%lx\n", eptr->ex_type); + } + eptr++; + } + post("\n"); +} + +#ifdef _WIN32 +void ABORT( void) {bug("expr");} +#endif diff --git a/ports/camomile/source/LibPd/pure-data/src/x_vexp.h b/ports/camomile/source/LibPd/pure-data/src/x_vexp.h new file mode 100644 index 00000000..608a64a4 --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_vexp.h @@ -0,0 +1,256 @@ +/* Copyright (c) IRCAM. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* "expr" was written by Shahrokh Yadegari c. 1989. -msp */ +/* "expr~" and "fexpr~" conversion by Shahrokh Yadegari c. 1999,2000 */ + +#define MSP +#ifdef PD +#undef MSP +#endif + +#ifdef PD +#include "m_pd.h" +#else /* MSP */ +#include "ext.h" +#include "z_dsp.h" +#endif + +#define fts_malloc malloc +#define fts_calloc calloc +#define fts_free free +#define fts_realloc realloc +#define fts_atom_t t_atom +#define fts_object_t t_object +typedef t_symbol *fts_symbol_t; + +#ifdef MSP +#define t_atom Atom +#define t_symbol Symbol +#define pd_new(x) newobject(x); +#define pd_free(x) freeobject(x); +#define t_outlet void +#define t_binbuf void +typedef t_class *t_pd; +typedef float t_floatarg; + +#include +#include +#include +#include +#include + +void pd_error(void *object, char *fmt, ...); + +#endif /* MSP */ + +#define post_error pd_error +#define fts_is_floatg(x) ((x)->a_type == A_FLOAT) + +#define fts_new_symbol_copy gensym + +#define fts_symbol_name(x) ((x)->s_name) + +/* + * Currently the maximum number of variables (inlets) that are supported + * is 10. + */ + +#define MAX_VARS 100 +#define MINODES 10 /* was 200 */ + +/* terminal defines */ + +/* + * operations + * (x<<16|y) x defines the level of precedence, + * the lower the number the lower the precedence + * separators are defines as operators just for convenience + */ + +#define OP_SEMI ((long)(1<<16|1)) /* ; */ +#define OP_COMMA ((long)(2<<16|2)) /* , */ +#define OP_STORE ((long)(3<<16|28)) /* = */ +#define OP_LOR ((long)(4<<16|3)) /* || */ +#define OP_LAND ((long)(5<<16|4)) /* && */ +#define OP_OR ((long)(6<<16|5)) /* | */ +#define OP_XOR ((long)(7<<16|6)) /* ^ */ +#define OP_AND ((long)(8<<16|7)) /* & */ +#define OP_NE ((long)(9<<16|8)) /* != */ +#define OP_EQ ((long)(9<<16|9)) /* == */ +#define OP_GE ((long)(10<<16|10)) /* >= */ +#define OP_GT ((long)(10<<16|11)) /* > */ +#define OP_LE ((long)(10<<16|12)) /* <= */ +#define OP_LT ((long)(10<<16|13)) /* < */ +#define OP_SR ((long)(11<<16|14)) /* >> */ +#define OP_SL ((long)(11<<16|15)) /* << */ +#define OP_SUB ((long)(12<<16|16)) /* - */ +#define OP_ADD ((long)(12<<16|17)) /* + */ +#define OP_MOD ((long)(13<<16|18)) /* % */ +#define OP_DIV ((long)(13<<16|19)) /* / */ +#define OP_MUL ((long)(13<<16|20)) /* * */ +#define OP_UMINUS ((long)(14<<16|21)) /* - unary minus */ +#define OP_NEG ((long)(14<<16|22)) /* ~ one complement */ +#define OP_NOT ((long)(14<<16|23)) /* ! */ +#define OP_RB ((long)(15<<16|24)) /* ] */ +#define OP_LB ((long)(15<<16|25)) /* [ */ +#define OP_RP ((long)(15<<16|26)) /* ) */ +#define OP_LP ((long)(15<<16|27)) /* ( */ +#define HI_PRE ((long)(100<<16)) /* infinite precedence */ +#define PRE_MASK ((long)0xffff0000) /* precedence level mask */ + +#define name_ok(c) (((c)=='_') || ((c)>='a' && (c)<='z') || \ + ((c)>='A' && (c)<='Z') || ((c) >= '0' && (c) <= '9')) +#define unary_op(x) ((x) == OP_NOT || (x) == OP_NEG || (x) == OP_UMINUS) + +struct ex_ex { + union { + long v_int; + t_float v_flt; + t_float *v_vec; /* this is an for allocated vector */ + long op; + char *ptr; + } ex_cont; /* content */ +#define ex_int ex_cont.v_int +#define ex_flt ex_cont.v_flt +#define ex_vec ex_cont.v_vec +#define ex_op ex_cont.op +#define ex_ptr ex_cont.ptr + long ex_type; /* type of the node */ + struct ex_ex *ex_end; /* the node after the end of this expression */ +}; +#define exNULL ((struct ex_ex *)0) + +/* defines for ex_type */ +#define ET_INT 1 /* an int */ +#define ET_FLT 2 /* a float */ +#define ET_OP 3 /* operator */ +#define ET_STR 4 /* string */ +#define ET_TBL 5 /* a table, the content is a pointer */ +#define ET_FUNC 6 /* a function */ +#define ET_SYM 7 /* symbol ("string") */ +#define ET_VSYM 8 /* variable symbol ("$s?") */ + /* we treat parenthesis and brackets */ + /* special to keep a pointer to their */ + /* match in the content */ +#define ET_LP 9 /* left parenthesis */ +#define ET_LB 10 /* left bracket */ +#define ET_II 11 /* and integer inlet */ +#define ET_FI 12 /* float inlet */ +#define ET_SI 13 /* string inlet */ +#define ET_VI 14 /* signal inlet */ +#define ET_VEC 15 /* allocated signal vector */ + /* special types for fexpr~ */ +#define ET_YO 16 /* vector output for fexpr~ */ +#define ET_YOM1 17 /* shorthand for $y?[-1] */ +#define ET_XI 18 /* vector input for fexpr~ */ +#define ET_XI0 20 /* shorthand for $x?[0] */ +#define ET_VAR 21 /* variable */ + +/* defines for ex_flags */ +#define EF_TYPE_MASK 0x07 /* first three bits define the type of expr */ +#define EF_EXPR 0x01 /* expr - control in and out */ +#define EF_EXPR_TILDE 0x02 /* expr~ signal and control in, signal out */ +#define EF_FEXPR_TILDE 0x04 /* fexpr~ filter expression */ + +#define EF_STOP 0x08 /* is it stopped used for expr~ and fexpr~ */ +#define EF_VERBOSE 0x10 /* verbose mode */ + +#define IS_EXPR(x) ((((x)->exp_flags&EF_TYPE_MASK)|EF_EXPR) == EF_EXPR) +#define IS_EXPR_TILDE(x) \ + ((((x)->exp_flags&EF_TYPE_MASK)|EF_EXPR_TILDE)==EF_EXPR_TILDE) +#define IS_FEXPR_TILDE(x) \ + ((((x)->exp_flags&EF_TYPE_MASK)|EF_FEXPR_TILDE)==EF_FEXPR_TILDE) + +#define SET_EXPR(x) (x)->exp_flags |= EF_EXPR; \ + (x)->exp_flags &= ~EF_EXPR_TILDE; \ + (x)->exp_flags &= ~EF_FEXPR_TILDE; + +#define SET_EXPR_TILDE(x) (x)->exp_flags &= ~EF_EXPR; \ + (x)->exp_flags |= EF_EXPR_TILDE; \ + (x)->exp_flags &= ~EF_FEXPR_TILDE; + +#define SET_FEXPR_TILDE(x) (x)->exp_flags &= ~EF_EXPR; \ + (x)->exp_flags &= ~EF_EXPR_TILDE; \ + (x)->exp_flags |= EF_FEXPR_TILDE; + +/* + * defines for expr_error + */ +#define EE_DZ 0x01 /* divide by zero error */ +#define EE_BI_OUTPUT 0x02 /* Bad output index */ +#define EE_BI_INPUT 0x04 /* Bad input index */ +#define EE_NOTABLE 0x08 /* NO TABLE */ +#define EE_NOVAR 0x10 /* NO VARIABLE */ + +typedef struct expr { +#ifdef PD + t_object exp_ob; +#else /* MSP */ + t_pxobject exp_ob; +#endif + int exp_flags; /* are we expr~, fexpr~, or expr */ + int exp_error; /* reported errors */ + int exp_nexpr; /* number of expressions */ + char *exp_string; /* the full expression string */ + char *exp_str; /* current parsing position */ + t_outlet *exp_outlet[MAX_VARS]; +#ifdef PD + struct _exprproxy *exp_proxy; +#else /* MAX */ + void *exp_proxy[MAX_VARS]; + long exp_proxy_id; +#endif + struct ex_ex *exp_stack[MAX_VARS]; + struct ex_ex exp_var[MAX_VARS]; + struct ex_ex exp_res[MAX_VARS]; /* the evluation result */ + t_float *exp_p_var[MAX_VARS]; + t_float *exp_p_res[MAX_VARS]; /* the previous evaluation result */ + t_float *exp_tmpres[MAX_VARS]; /* temporty result for fexpr~ */ + int exp_vsize; /* the size of the signal vector */ + int exp_nivec; /* # of vector inlets */ + t_float exp_f; /* control value to be transformed to signal */ +} t_expr; + +typedef struct ex_funcs { + char *f_name; /* function name */ + void (*f_func)(t_expr *, long, struct ex_ex *, struct ex_ex *); + /* the real function performing the function (void, no return!!!) */ + long f_argc; /* number of arguments */ +} t_ex_func; + +/* function prototypes for pd-related functions called withing vexp.h */ + +extern int +max_ex_tab_store(struct expr *expr, t_symbol *s, struct ex_ex *arg, + struct ex_ex *rval, struct ex_ex *optr); +extern int +max_ex_tab(struct expr *expr, t_symbol *s, struct ex_ex *arg, + struct ex_ex *optr); +extern int max_ex_var(struct expr *expr, t_symbol *s, struct ex_ex *optr, + int idx); +extern int max_ex_var_store(struct expr *, t_symbol *, struct ex_ex *, struct ex_ex *); +extern int ex_getsym(char *p, t_symbol **s); +extern const char *ex_symname(t_symbol *s); +void ex_mkvector(t_float *fp, t_float x, int size); +extern void ex_size(t_expr *expr, long int argc, struct ex_ex *argv, + struct ex_ex *optr); +extern void ex_sum(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +extern void ex_Sum(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +extern void ex_avg(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +extern void ex_Avg(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +extern void ex_store(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); + +int value_getonly(t_symbol *s, t_float *f); + + +/* These pragmas are only used for MSVC, not MinGW or Cygwin */ +#ifdef _MSC_VER +#pragma warning (disable: 4305 4244) +#endif + +#ifdef _WIN32 +#define abort ABORT +void ABORT(void); +#endif diff --git a/ports/camomile/source/LibPd/pure-data/src/x_vexp_fun.c b/ports/camomile/source/LibPd/pure-data/src/x_vexp_fun.c new file mode 100644 index 00000000..24b96f3d --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_vexp_fun.c @@ -0,0 +1,1343 @@ +/* Copyright (c) IRCAM. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* "expr" was written by Shahrokh Yadegari c. 1989. -msp + * + * Nov. 2001 --sdy + * conversion for expr~ + * + * Jan, 2002 --sdy + * added fmod() + * + * May 2002 + * added floor and ceil for expr -- Orm Finnendahl + * + * July 2002 --sdy + * added the following math functions: + * cbrt - cube root + * erf - error function + * erfc - complementary error function + * expm1 - exponential minus 1, + * log1p - logarithm of 1 plus + * isinf - is the value infinite, + * finite - is the value finite + * isnan -- is the resut a nan (Not a number) + * copysign - copy sign of a number + * ldexp - multiply floating-point number by integral power of 2 + * imodf - get signed integral value from floating-point number + * modf - get signed fractional value from floating-point number + * drem - floating-point remainder function + * + * The following are done but not popular enough in math libss + * to be included yet + * hypoth - Euclidean distance function + * trunc + * round + * nearbyint - + * November 2015 + * - drem() is now obsolete but it is kept here so that other patches do not break + * - added remainder() - floating-point remainder function + * - fixed the bug that unary operators could be used as + * binary ones (10 ~ 1) + * - fixed ceil() and floor() which should have only one argument + * - added copysign (the previous one "copysig" which was + * defined with one argument was kept for compatibility) + * - fixed sum("table"), and Sum("table", x, y) + * - deleted avg(), Avg() as they can be simple expressions + * - deleted store as this can be achieved by the '=' operator + * July 2017 --sdy + * + * - ex_if() is reworked to only evaluate either the left or the right arg + */ + + + +/* + * vexp_func.c -- this file include all the functions for vexp. + * the first two arguments to the function are the number + * of argument and an array of arguments (argc, argv) + * the last argument is a pointer to a struct ex_ex for + * the result. Up do this point, the content of the + * struct ex_ex that these functions receive are either + * ET_INT (long), ET_FLT (t_float), or ET_SYM (char **, it is + * char ** and not char * since NewHandle of Mac returns + * a char ** for relocatability.) The common practice in + * these functions is that they figure out the type of their + * result according to the type of the arguments. In general + * the ET_SYM is used an ET_INT when we expect a value. + * It is the users responsibility not to pass strings to the + * function. + */ + +#include +#include + +#define __STRICT_BSD__ +#include +#undef __STRICT_BSD__ + +#include "x_vexp.h" + +struct ex_ex *ex_eval(struct expr *expr, struct ex_ex *eptr, + struct ex_ex *optr, int i); + +/* forward declarations */ + +static void ex_min(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_max(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_toint(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_rint(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_tofloat(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_pow(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_exp(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_log(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_ln(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_sin(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_cos(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_asin(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_acos(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_tan(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_atan(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_sinh(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_cosh(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_asinh(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_acosh(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_tanh(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_atanh(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_atan2(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_sqrt(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_fact(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_random(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_abs(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_fmod(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_ceil(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_floor(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +struct ex_ex * ex_if(t_expr *expr, struct ex_ex *argv, struct ex_ex *optr, + struct ex_ex *args, int idx); +static void ex_ldexp(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_imodf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_modf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +#if !defined(_MSC_VER) || (_MSC_VER >= 17000) +static void ex_cbrt(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_erf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_erfc(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_expm1(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_log1p(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_isinf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_finite(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_isnan(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_copysign(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_drem(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_remainder(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_round(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_trunc(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_nearbyint(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +#endif +#ifdef notdef +/* the following will be added once they are more popular in math libraries */ +static void ex_hypoth(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +#endif + + +t_ex_func ex_funcs[] = { + {"min", ex_min, 2}, + {"max", ex_max, 2}, + {"int", ex_toint, 1}, + {"rint", ex_rint, 1}, + {"float", ex_tofloat, 1}, + {"fmod", ex_fmod, 2}, + {"floor", ex_floor, 1}, + {"ceil", ex_ceil, 1}, + {"pow", ex_pow, 2}, + {"sqrt", ex_sqrt, 1}, + {"exp", ex_exp, 1}, + {"log10", ex_log, 1}, + {"ln", ex_ln, 1}, + {"log", ex_ln, 1}, + {"sin", ex_sin, 1}, + {"cos", ex_cos, 1}, + {"tan", ex_tan, 1}, + {"asin", ex_asin, 1}, + {"acos", ex_acos, 1}, + {"atan", ex_atan, 1}, + {"atan2", ex_atan2, 2}, + {"sinh", ex_sinh, 1}, + {"cosh", ex_cosh, 1}, + {"tanh", ex_tanh, 1}, + {"fact", ex_fact, 1}, + {"random", ex_random, 2}, /* random number */ + {"abs", ex_abs, 1}, + {"if", (void (*))ex_if, 3}, + {"ldexp", ex_ldexp, 2}, + {"imodf", ex_imodf, 1}, + {"modf", ex_modf, 1}, +#if !defined(_MSC_VER) || (_MSC_VER >= 17000) + {"asinh", ex_asinh, 1}, + {"acosh", ex_acosh, 1}, + {"atanh", ex_atanh, 1}, /* hyperbolic atan */ + {"isnan", ex_isnan, 1}, + {"cbrt", ex_cbrt, 1}, + {"round", ex_round, 1}, + {"trunc", ex_trunc, 1}, + {"erf", ex_erf, 1}, + {"erfc", ex_erfc, 1}, + {"expm1", ex_expm1, 1}, + {"log1p", ex_log1p, 1}, + {"finite", ex_finite, 1}, + {"nearbyint", ex_nearbyint, 1}, + {"copysign", ex_copysign, 2}, + {"isinf", ex_isinf, 1}, + {"remainder", ex_remainder, 2}, +#endif +#ifdef PD + {"size", ex_size, 1}, + {"sum", ex_sum, 1}, + {"Sum", ex_Sum, 3}, + {"avg", ex_avg, 1}, + {"Avg", ex_Avg, 3}, +#endif +#ifdef notdef +/* the following will be added once they are more popular in math libraries */ + {"hypoth", ex_hypoth, 1}, +#endif + {0, 0, 0} +}; + +/* + * FUN_EVAL -- do type checking, evaluate a function, + * if fltret is set return float + * otherwise return value based on regular typechecking, + */ +#define FUNC_EVAL(left, right, func, leftfuncast, rightfuncast, optr, fltret) \ +switch (left->ex_type) { \ +case ET_INT: \ + switch(right->ex_type) { \ + case ET_INT: \ + if (optr->ex_type == ET_VEC) { \ + op = optr->ex_vec; \ + scalar = (t_float)func(leftfuncast left->ex_int, \ + rightfuncast right->ex_int); \ + j = e->exp_vsize; \ + while (j--) \ + *op++ = scalar; \ + } else { \ + if (fltret) { \ + optr->ex_type = ET_FLT; \ + optr->ex_flt = (t_float)func(leftfuncast \ + left->ex_int, rightfuncast right->ex_int); \ + } else { \ + optr->ex_type = ET_INT; \ + optr->ex_int = (int)func(leftfuncast \ + left->ex_int, rightfuncast right->ex_int); \ + } \ + } \ + break; \ + case ET_FLT: \ + if (optr->ex_type == ET_VEC) { \ + op = optr->ex_vec; \ + scalar = (t_float)func(leftfuncast left->ex_int, \ + rightfuncast right->ex_flt); \ + j = e->exp_vsize; \ + while (j--) \ + *op++ = scalar; \ + } else { \ + optr->ex_type = ET_FLT; \ + optr->ex_flt = (t_float)func(leftfuncast left->ex_int, \ + rightfuncast right->ex_flt); \ + } \ + break; \ + case ET_VEC: \ + case ET_VI: \ + if (optr->ex_type != ET_VEC) { \ + if (optr->ex_type == ET_VI) { \ + post("expr~: Int. error %d", __LINE__); \ + abort(); \ + } \ + optr->ex_type = ET_VEC; \ + optr->ex_vec = (t_float *) \ + fts_malloc(sizeof (t_float)*e->exp_vsize); \ + } \ + scalar = left->ex_int; \ + rp = right->ex_vec; \ + op = optr->ex_vec; \ + j = e->exp_vsize; \ + while (j--) { \ + *op++ = (t_float)func(leftfuncast scalar, \ + rightfuncast *rp); \ + rp++; \ + } \ + break; \ + case ET_SYM: \ + default: \ + post_error((fts_object_t *) e, \ + "expr: FUNC_EVAL(%d): bad right type %ld\n", \ + __LINE__, right->ex_type);\ + } \ + break; \ +case ET_FLT: \ + switch(right->ex_type) { \ + case ET_INT: \ + if (optr->ex_type == ET_VEC) { \ + op = optr->ex_vec; \ + scalar = (t_float)func(leftfuncast left->ex_flt, \ + rightfuncast right->ex_int); \ + j = e->exp_vsize; \ + while (j--) \ + *op++ = scalar; \ + } else { \ + optr->ex_type = ET_FLT; \ + optr->ex_flt = (t_float)func(leftfuncast left->ex_flt, \ + rightfuncast right->ex_int); \ + } \ + break; \ + case ET_FLT: \ + if (optr->ex_type == ET_VEC) { \ + op = optr->ex_vec; \ + scalar = (t_float)func(leftfuncast left->ex_flt, \ + rightfuncast right->ex_flt); \ + j = e->exp_vsize; \ + while (j--) \ + *op++ = scalar; \ + } else { \ + optr->ex_type = ET_FLT; \ + optr->ex_flt = (t_float)func(leftfuncast left->ex_flt, \ + rightfuncast right->ex_flt); \ + } \ + break; \ + case ET_VEC: \ + case ET_VI: \ + if (optr->ex_type != ET_VEC) { \ + if (optr->ex_type == ET_VI) { \ + post("expr~: Int. error %d", __LINE__); \ + abort(); \ + } \ + optr->ex_type = ET_VEC; \ + optr->ex_vec = (t_float *) \ + fts_malloc(sizeof (t_float) * e->exp_vsize);\ + } \ + scalar = left->ex_flt; \ + rp = right->ex_vec; \ + op = optr->ex_vec; \ + j = e->exp_vsize; \ + while (j--) { \ + *op++ = (t_float)func(leftfuncast scalar, \ + rightfuncast *rp); \ + rp++; \ + } \ + break; \ + case ET_SYM: \ + default: \ + post_error((fts_object_t *) e, \ + "expr: FUNC_EVAL(%d): bad right type %ld\n", \ + __LINE__, right->ex_type);\ + } \ + break; \ +case ET_VEC: \ +case ET_VI: \ + if (optr->ex_type != ET_VEC) { \ + if (optr->ex_type == ET_VI) { \ + post("expr~: Int. error %d", __LINE__); \ + abort(); \ + } \ + optr->ex_type = ET_VEC; \ + optr->ex_vec = (t_float *) \ + fts_malloc(sizeof (t_float) * e->exp_vsize); \ + } \ + op = optr->ex_vec; \ + lp = left->ex_vec; \ + switch(right->ex_type) { \ + case ET_INT: \ + scalar = right->ex_int; \ + j = e->exp_vsize; \ + while (j--) { \ + *op++ = (t_float)func(leftfuncast *lp, \ + rightfuncast scalar); \ + lp++; \ + } \ + break; \ + case ET_FLT: \ + scalar = right->ex_flt; \ + j = e->exp_vsize; \ + while (j--) { \ + *op++ = (t_float)func(leftfuncast *lp, \ + rightfuncast scalar); \ + lp++; \ + } \ + break; \ + case ET_VEC: \ + case ET_VI: \ + rp = right->ex_vec; \ + j = e->exp_vsize; \ + while (j--) { \ + /* \ + * on a RISC processor one could copy \ + * 8 times in each round to get a considerable \ + * improvement \ + */ \ + *op++ = (t_float)func(leftfuncast *lp, \ + rightfuncast *rp); \ + rp++; lp++; \ + } \ + break; \ + case ET_SYM: \ + default: \ + post_error((fts_object_t *) e, \ + "expr: FUNC_EVAL(%d): bad right type %ld\n", \ + __LINE__, right->ex_type);\ + } \ + break; \ +case ET_SYM: \ +default: \ + post_error((fts_object_t *) e, \ + "expr: FUNC_EVAL(%d): bad left type %ld\n", \ + __LINE__, left->ex_type); \ +} + +/* + * FUNC_EVAL_UNARY - evaluate a unary function, + * if fltret is set return t_float + * otherwise return value based on regular typechecking, + */ +#define FUNC_EVAL_UNARY(left, func, leftcast, optr, fltret) \ +switch(left->ex_type) { \ +case ET_INT: \ + if (optr->ex_type == ET_VEC) { \ + ex_mkvector(optr->ex_vec, \ + (t_float)(func (leftcast left->ex_int)), e->exp_vsize);\ + break; \ + } \ + if (fltret) { \ + optr->ex_type = ET_FLT; \ + optr->ex_flt = (t_float) func(leftcast left->ex_int); \ + break; \ + } \ + optr->ex_type = ET_INT; \ + optr->ex_int = (int) func(leftcast left->ex_int); \ + break; \ +case ET_FLT: \ + if (optr->ex_type == ET_VEC) { \ + ex_mkvector(optr->ex_vec, \ + (t_float)(func (leftcast left->ex_flt)), e->exp_vsize);\ + break; \ + } \ + optr->ex_type = ET_FLT; \ + optr->ex_flt = (t_float) func(leftcast left->ex_flt); \ + break; \ +case ET_VI: \ +case ET_VEC: \ + if (optr->ex_type != ET_VEC) { \ + optr->ex_type = ET_VEC; \ + optr->ex_vec = (t_float *) \ + fts_malloc(sizeof (t_float)*e->exp_vsize); \ + } \ + op = optr->ex_vec; \ + lp = left->ex_vec; \ + j = e->exp_vsize; \ + while (j--) \ + *op++ = (t_float)(func (leftcast *lp++)); \ + break; \ +default: \ + post_error((fts_object_t *) e, \ + "expr: FUNV_EVAL_UNARY(%d): bad left type %ld\n",\ + __LINE__, left->ex_type); \ +} + +#undef min +#undef max +#define min(x,y) (x > y ? y : x) +#define max(x,y) (x > y ? x : y) + +#define FUNC_DEF(ex_func, func, castleft, castright, fltret); \ +static void \ +ex_func(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)\ +{ \ + struct ex_ex *left, *right; \ + t_float *op; /* output pointer */ \ + t_float *lp, *rp; /* left and right vector pointers */ \ + t_float scalar; \ + int j; \ + \ + left = argv++; \ + right = argv; \ + FUNC_EVAL(left, right, func, castleft, castright, optr, fltret); \ +} + + +#define FUNC_DEF_UNARY(ex_func, func, cast, fltret); \ +static void \ +ex_func(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)\ +{ \ + struct ex_ex *left; \ + t_float *op; /* output pointer */ \ + t_float *lp, *rp; /* left and right vector pointers */ \ + t_float scalar; \ + int j; \ + \ + left = argv++; \ + \ + FUNC_EVAL_UNARY(left, func, cast, optr, fltret); \ +} + +/* + * ex_min -- if any of the arguments are or the output are vectors, a vector + * of floats is generated otherwise the type of the result is the + * type of the smaller value + */ +static void +ex_min(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left, *right; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + right = argv; + + FUNC_EVAL(left, right, min, (double), (double), optr, 0); +} + +/* + * ex_max -- if any of the arguments are or the output are vectors, a vector + * of floats is generated otherwise the type of the result is the + * type of the larger value + */ +static void +ex_max(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left, *right; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + right = argv; + + FUNC_EVAL(left, right, max, (double), (double), optr, 0); +} + +/* + * ex_toint -- convert to integer + */ +static void +ex_toint(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + +#define toint(x) ((int)(x)) + FUNC_EVAL_UNARY(left, toint, (int), optr, 0); + } + +/* + * ex_rint -- rint() round to the nearest int according to the common + * rounding mechanism + */ +static void +ex_rint(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + + FUNC_EVAL_UNARY(left, rint, (double), optr, 1); +} + +/* + * ex_tofloat -- convert to t_float + */ +static void +ex_tofloat(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + +#define tofloat(x) ((t_float)(x)) + FUNC_EVAL_UNARY(left, tofloat, (t_float), optr, 1); +} + + +/* + * ex_pow -- the power of + */ +static void +ex_pow(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left, *right; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + right = argv; + FUNC_EVAL(left, right, pow, (double), (double), optr, 1); +} + +/* + * ex_sqrt -- square root + */ +static void +ex_sqrt(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, sqrt, (double), optr, 1); +} + +/* + * ex_exp -- e to the power of + */ +static void +ex_exp(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, exp, (double), optr, 1); +} + +/* + * ex_log -- 10 based logarithm + */ +static void +ex_log(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, log10, (double), optr, 1); +} + +/* + * ex_ln -- natural log + */ +static void +ex_ln(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, log, (double), optr, 1); +} + +static void +ex_sin(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, sin, (double), optr, 1); +} + +static void +ex_cos(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, cos, (double), optr, 1); +} + + +static void +ex_tan(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, tan, (double), optr, 1); +} + +static void +ex_asin(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, asin, (double), optr, 1); +} + +static void +ex_acos(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, acos, (double), optr, 1); +} + + +static void +ex_atan(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, atan, (double), optr, 1); +} + +/* + *ex_atan2 -- + */ +static void +ex_atan2(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left, *right; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + right = argv; + FUNC_EVAL(left, right, atan2, (double), (double), optr, 1); +} + +/* + * ex_fmod -- floating point modulo + */ +static void +ex_fmod(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left, *right; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + right = argv; + FUNC_EVAL(left, right, fmod, (double), (double), optr, 1); +} + + +/* + * ex_floor -- floor + */ +static void +ex_floor(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + FUNC_EVAL_UNARY(left, floor, (double), optr, 1); +} + + +/* + * ex_ceil -- ceil + */ +static void +ex_ceil(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + FUNC_EVAL_UNARY(left, ceil, (double), optr, 1); +} + +static void +ex_sinh(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, sinh, (double), optr, 1); +} + +static void +ex_cosh(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, cosh, (double), optr, 1); +} + + +static void +ex_tanh(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, tanh, (double), optr, 1); +} + + +#if !defined(_MSC_VER) || (_MSC_VER >= 17000) +static void +ex_asinh(t_expr *e, long argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, asinh, (double), optr, 1); +} + +static void +ex_acosh(t_expr *e, long argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, acosh, (double), optr, 1); +} + +static void +ex_atanh(t_expr *e, long argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, atanh, (double), optr, 1); +} +#endif + +static int +ex_dofact(int i) +{ + int ret = 0; + + if (i) + ret = 1; + else + return (1); + + do { + ret *= i; + } while (--i); + + return(ret); +} + +static void +ex_fact(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, ex_dofact, (int), optr, 0); +} + +static int +ex_dorandom(int i1, int i2) +{ + int i; + int j; + + j = rand() & 0x7fffL; + i = i1 + (int)((((float)(i2 - i1)) * (float)j) / pow (2, 15)); + return (i); +} +/* + * ex_random -- return a random number + */ +static void +ex_random(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left, *right; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + right = argv; + FUNC_EVAL(left, right, ex_dorandom, (int), (int), optr, 0); +} + + +static void +ex_abs(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float scalar; + int j; + + left = argv++; + + FUNC_EVAL_UNARY(left, fabs, (double), optr, 0); +} + +/* + * ex_if -- if function + */ +struct ex_ex * +ex_if(t_expr *e, struct ex_ex *eptr, struct ex_ex *optr, struct ex_ex *argv, int idx) +{ + struct ex_ex *left, *right, *cond, *res; + t_float *op; /* output pointer */ + t_float *lp, *rp; /* left and right vector pointers */ + t_float *cp; /* condition pointer */ + t_float leftvalue, rightvalue; + int j; + int condtrue = 0; + + // evaluate the condition + eptr = ex_eval(e, eptr, argv, idx); + cond = argv++; + // only either the left or right will be evaluated depending + // on the truth value of the condition + // However, if the condition is a vector, both args will be evaluated + + switch (cond->ex_type) { + case ET_VEC: + case ET_VI: + if (optr->ex_type != ET_VEC) { + if (optr->ex_type == ET_VI) { + /* SDY remove this test */ + post("expr~: Int. error %d", __LINE__); + return (eptr); + } + optr->ex_type = ET_VEC; + optr->ex_vec = (t_float *) + fts_malloc(sizeof (t_float) * e->exp_vsize); + if (!optr->ex_vec) { + post("expr:if: no mem"); + /* pass over the left and right args */ + return(cond->ex_end->ex_end); + } + } + /* + * if the condition is a vector + * the left and the right args both will get processed + */ + eptr = ex_eval(e, eptr, argv, idx); + left = argv++; + eptr = ex_eval(e, eptr, argv, idx); + right = argv; + op = optr->ex_vec; + j = e->exp_vsize; + cp = cond->ex_vec; + switch (left->ex_type) { + case ET_INT: + leftvalue = left->ex_int; + switch (right->ex_type) { + case ET_INT: + rightvalue = right->ex_int; + while (j--) { + if (*cp++) + *op++ = leftvalue; + else + *op++ = rightvalue; + } + return (eptr); + case ET_FLT: + rightvalue = right->ex_flt; + while (j--) { + if (*cp++) + *op++ = leftvalue; + else + *op++ = rightvalue; + } + return (eptr); + case ET_VEC: + case ET_VI: + rp = right->ex_vec; + while (j--) { + if (*cp++) + *op++ = leftvalue; + else + *op++ = *rp; + rp++; + } + return (eptr); + case ET_SYM: + default: + post_error((fts_object_t *) e, + "expr: FUNC_EVAL(%d): bad right type %ld\n", + __LINE__, right->ex_type); + return (eptr); + } + case ET_FLT: + leftvalue = left->ex_flt; + switch (right->ex_type) { + case ET_INT: + rightvalue = right->ex_int; + while (j--) { + if (*cp++) + *op++ = leftvalue; + else + *op++ = rightvalue; + } + return (eptr); + case ET_FLT: + rightvalue = right->ex_flt; + while (j--) { + if (*cp++) + *op++ = leftvalue; + else + *op++ = rightvalue; + } + return (eptr); + case ET_VEC: + case ET_VI: + rp = right->ex_vec; + while (j--) { + if (*cp++) + *op++ = leftvalue; + else + *op++ = *rp; + rp++; + } + return (eptr); + case ET_SYM: + default: + post_error((fts_object_t *) e, + "expr: FUNC_EVAL(%d): bad right type %ld\n", + __LINE__, right->ex_type); + return (eptr); + } + case ET_VEC: + case ET_VI: + lp = left->ex_vec; + switch (right->ex_type) { + case ET_INT: + rightvalue = right->ex_int; + while (j--) { + if (*cp++) + *op++ = *lp; + else + *op++ = rightvalue; + lp++; + } + return (eptr); + case ET_FLT: + rightvalue = right->ex_flt; + while (j--) { + if (*cp++) + *op++ = *lp; + else + *op++ = rightvalue; + lp++; + } + return (eptr); + case ET_VEC: + case ET_VI: + rp = right->ex_vec; + while (j--) { + if (*cp++) + *op++ = *lp; + else + *op++ = *rp; + lp++; rp++; + } + return (eptr); + case ET_SYM: + default: + post_error((fts_object_t *) e, + "expr: FUNC_EVAL(%d): bad right type %ld\n", + __LINE__, right->ex_type); + return (eptr); + } + case ET_SYM: + default: + post_error((fts_object_t *) e, + "expr: FUNC_EVAL(%d): bad left type %ld\n", + __LINE__, left->ex_type); + return (eptr); + } + case ET_INT: + if (cond->ex_int) + condtrue = 1; + else + condtrue = 0; + break; + case ET_FLT: + if (cond->ex_flt) + condtrue = 1; + else + condtrue = 0; + break; + case ET_SYM: + default: + post_error((fts_object_t *) e, + "expr: FUNC_EVAL(%d): bad condition type %ld\n", + __LINE__, cond->ex_type); + return (eptr); + } + if (condtrue) { + eptr = ex_eval(e, eptr, argv, idx); + res = argv++; + eptr = eptr->ex_end; /* no right processing */ + + } else { + eptr = eptr->ex_end; /* no left rocessing */ + eptr = ex_eval(e, eptr, argv, idx); + res = argv++; + } + switch(res->ex_type) { + case ET_INT: + if (optr->ex_type == ET_VEC) { + ex_mkvector(optr->ex_vec, (t_float)res->ex_int, + e->exp_vsize); + return (eptr); + } + *optr = *res; + return (eptr); + case ET_FLT: + if (optr->ex_type == ET_VEC) { + ex_mkvector(optr->ex_vec, (t_float)res->ex_flt, + e->exp_vsize); + return (eptr); + } + *optr = *res; + return (eptr); + case ET_VEC: + case ET_VI: + if (optr->ex_type != ET_VEC) { + if (optr->ex_type == ET_VI) { + /* SDY remove this test */ + post("expr~: Int. error %d", __LINE__); + return (eptr); + } + optr->ex_type = ET_VEC; + optr->ex_vec = (t_float *) + fts_malloc(sizeof (t_float) * e->exp_vsize); + if (!optr->ex_vec) { + post("expr:if: no mem"); + return (eptr); + } + } + memcpy(optr->ex_vec, res->ex_vec, e->exp_vsize*sizeof(t_float)); + return (eptr); + case ET_SYM: + default: + post_error((fts_object_t *) e, + "expr: FUNC_EVAL(%d): bad res type %ld\n", + __LINE__, res->ex_type); + return (eptr); + } + +} + +/* + * ex_imodf - extract signed integral value from floating-point number + */ +static double +imodf(double x) +{ + double xx; + + modf(x, &xx); + return (xx); +} +FUNC_DEF_UNARY(ex_imodf, imodf, (double), 1); + +/* + * ex_modf - extract signed fractional value from floating-point number + * + * using fracmodf because fmodf() is already defined in a .h file + */ +static double +fracmodf(double x) +{ + double xx; + + return(modf(x, &xx)); +} +FUNC_DEF_UNARY(ex_modf, fracmodf, (double), 1); + +/* + * ex_ldexp - multiply floating-point number by integral power of 2 + */ +FUNC_DEF(ex_ldexp, ldexp, (double), (int), 1); + +#if !defined(_MSC_VER) || (_MSC_VER >= 17000) +/* + * ex_cbrt - cube root + */ +FUNC_DEF_UNARY(ex_cbrt, cbrt, (double), 1); + +/* + * ex_erf - error function + */ +FUNC_DEF_UNARY(ex_erf, erf, (double), 1); + +/* + * ex_erfc - complementary error function + */ +FUNC_DEF_UNARY(ex_erfc, erfc, (double), 1); + +/* + * ex_expm1 - exponential minus 1, + */ +FUNC_DEF_UNARY(ex_expm1, expm1, (double), 1); + +/* + * ex_log1p - logarithm of 1 plus + */ +FUNC_DEF_UNARY(ex_log1p, log1p, (double), 1); + +/* + * ex_isinf - is the value infinite, + */ +FUNC_DEF_UNARY(ex_isinf, isinf, (double), 0); + +/* + * ex_finite - is the value finite + */ +FUNC_DEF_UNARY(ex_finite, isfinite, (double), 0); + +/* + * ex_isnan -- is the resut a nan (Not a number) + */ +FUNC_DEF_UNARY(ex_isnan, isnan, (double), 0); + +/* + * ex_copysign - copy sign of a number + */ +FUNC_DEF(ex_copysign, copysign, (double), (double), 1); + +/* + * drem() is now obsolute + * ex_drem - floating-point remainder function + */ +FUNC_DEF(ex_drem, remainder, (double), (double), 1); + +/* + * ex_remainder - floating-point remainder function + */ +FUNC_DEF(ex_remainder, remainder, (double), (double), 1); + +/* + * ex_round - round to nearest integer, away from zero + */ +FUNC_DEF_UNARY(ex_round, round, (double), 1); + +/* + * ex_trunc - round to integer, towards zero + */ +FUNC_DEF_UNARY(ex_trunc, trunc, (double), 1); + +/* + * ex_nearbyint - round to nearest integer + */ +FUNC_DEF_UNARY(ex_nearbyint, nearbyint, (double), 1); + +#endif + +#ifdef notdef +/* the following will be added once they are more popular in math libraries */ +/* + * ex_hypoth - Euclidean distance function + */ +FUNC_DEF(ex_hypoth, hypoth, (double), (double), 1); + +#endif diff --git a/ports/camomile/source/LibPd/pure-data/src/x_vexp_if.c b/ports/camomile/source/LibPd/pure-data/src/x_vexp_if.c new file mode 100644 index 00000000..76a93aed --- /dev/null +++ b/ports/camomile/source/LibPd/pure-data/src/x_vexp_if.c @@ -0,0 +1,1368 @@ +/* Copyright (c) IRCAM. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* "expr" was written by Shahrokh Yadegari c. 1989. -msp */ +/* "expr~" and "fexpr~" conversion by Shahrokh Yadegari c. 1999,2000 */ + +/* + * Feb 2002 - added access to variables + * multiple expression support + * new short hand forms for fexpr~ + * now $y or $y1 = $y1[-1] and $y2 = $y2[-1] + * --sdy + * + * + * version 0.50 - March 2016 + * version 0.55 - July 2017 + * version 0.56 - January 2018 + */ + +#include +#include +#include + +#include "x_vexp.h" + +static char *exp_version = "0.55"; + +extern struct ex_ex *ex_eval(struct expr *expr, struct ex_ex *eptr, + struct ex_ex *optr, int n); + +#ifdef PD +static t_class *expr_class; +static t_class *expr_tilde_class; +static t_class *fexpr_tilde_class; +#else /* MSP */ +void *expr_tilde_class; +#endif + + +/*------------------------- expr class -------------------------------------*/ + +extern int expr_donew(struct expr *expr, int ac, t_atom *av); + +/*#define EXPR_DEBUG*/ + +static void expr_bang(t_expr *x); +t_int *expr_perform(t_int *w); + + +static void +expr_list(t_expr *x, t_symbol *s, int argc, const fts_atom_t *argv) +{ + int i; + + if (argc > MAX_VARS) argc = MAX_VARS; + + for (i = 0; i < argc; i++) + { + if (argv[i].a_type == A_FLOAT) + { + if (x->exp_var[i].ex_type == ET_FI) + x->exp_var[i].ex_flt = argv[i].a_w.w_float; + else if (x->exp_var[i].ex_type == ET_II) + x->exp_var[i].ex_int = argv[i].a_w.w_float; + else if (x->exp_var[i].ex_type) + pd_error(x, "expr: type mismatch"); + } + else if (argv[i].a_type == A_SYMBOL) + { + if (x->exp_var[i].ex_type == ET_SI) + x->exp_var[i].ex_ptr = (char *)argv[i].a_w.w_symbol; + else if (x->exp_var[i].ex_type) + pd_error(x, "expr: type mismatch"); + } + } + expr_bang(x); +} + +static void +expr_flt(t_expr *x, t_float f, int in) +{ + if (in >= MAX_VARS) + return; + + if (x->exp_var[in].ex_type == ET_FI) + x->exp_var[in].ex_flt = f; + else if (x->exp_var[in].ex_type == ET_II) + x->exp_var[in].ex_int = f; +} + +static t_class *exprproxy_class; + +typedef struct _exprproxy { + t_pd p_pd; + int p_index; + t_expr *p_owner; + struct _exprproxy *p_next; +} t_exprproxy; + +t_exprproxy *exprproxy_new(t_expr *owner, int indx); +void exprproxy_float(t_exprproxy *p, t_floatarg f); + +t_exprproxy * +exprproxy_new(t_expr *owner, int indx) +{ + t_exprproxy *x = (t_exprproxy *)pd_new(exprproxy_class); + x->p_owner = owner; + x->p_index = indx; + x->p_next = owner->exp_proxy; + owner->exp_proxy = x; + return (x); +} + +void +exprproxy_float(t_exprproxy *p, t_floatarg f) +{ + t_expr *x = p->p_owner; + int in = p->p_index; + + if (in >= MAX_VARS) + return; + + if (x->exp_var[in].ex_type == ET_FI) + x->exp_var[in].ex_flt = f; + else if (x->exp_var[in].ex_type == ET_II) + x->exp_var[in].ex_int = f; +} + +/* method definitions */ +static void +expr_ff(t_expr *x) +{ + t_exprproxy *y; + int i; + + y = x->exp_proxy; + while (y) + { + x->exp_proxy = y->p_next; +#ifdef PD + pd_free(&y->p_pd); +#else /*MSP */ + /* SDY find out what needs to be called for MSP */ + +#endif + y = x->exp_proxy; + } + for (i = 0 ; i < x->exp_nexpr; i++) + if (x->exp_stack[i]) + fts_free(x->exp_stack[i]); +/* + * SDY free all the allocated buffers here for expr~ and fexpr~ + * check to see if there are others + */ + for (i = 0; i < MAX_VARS; i++) { + if (x->exp_p_var[i]) + fts_free(x->exp_p_var[i]); + if (x->exp_p_res[i]) + fts_free(x->exp_p_res[i]); + if (x->exp_tmpres[i]) + fts_free(x->exp_tmpres[i]); + } + + +} + +static void +expr_bang(t_expr *x) +{ + int i; + +#ifdef EXPR_DEBUG + { + struct ex_ex *eptr; + + for (i = 0, eptr = x->exp_var; ; eptr++, i++) + { + if (!eptr->ex_type) + break; + switch (eptr->ex_type) + { + case ET_II: + fprintf(stderr,"ET_II: %d \n", eptr->ex_int); + break; + + case ET_FI: + fprintf(stderr,"ET_FT: %f \n", eptr->ex_flt); + break; + + default: + fprintf(stderr,"oups\n"); + } + } + } +#endif + /* banging a signal or filter object means nothing */ + if (!IS_EXPR(x)) + return; + + for (i = x->exp_nexpr - 1; i > -1 ; i--) { + if (!ex_eval(x, x->exp_stack[i], &x->exp_res[i], 0)) { + /*fprintf(stderr,"expr_bang(error evaluation)\n"); */ + /* SDY now that we have multiple ones, on error we should + * continue + return; + */ + } + switch(x->exp_res[i].ex_type) { + case ET_INT: + outlet_float(x->exp_outlet[i], + (t_float) x->exp_res[i].ex_int); + break; + + case ET_FLT: + outlet_float(x->exp_outlet[i], x->exp_res[i].ex_flt); + break; + + case ET_SYM: + /* CHANGE this will have to be taken care of */ + + default: + post("expr: bang: unrecognized result %ld\n", x->exp_res[i].ex_type); + } + } +} + +static t_expr * +#ifdef PD +expr_new(t_symbol *s, int ac, t_atom *av) +#else /* MSP */ +Nexpr_new(t_symbol *s, int ac, t_atom *av) +#endif +{ + struct expr *x; + int i, ninlet; + struct ex_ex *eptr; + t_atom fakearg; + int dsp_index; /* keeping track of the dsp inlets */ + + +/* + * SDY - we may need to call dsp_setup() in this function + */ + + if (!ac) + { + ac = 1; + av = &fakearg; + SETFLOAT(&fakearg, 0); + } + +#ifdef PD + /* + * figure out if we are expr, expr~, or fexpr~ + */ + if (!strcmp("expr", s->s_name)) { + x = (t_expr *)pd_new(expr_class); + SET_EXPR(x); + } else if (!strcmp("expr~", s->s_name)) { + x = (t_expr *)pd_new(expr_tilde_class); + SET_EXPR_TILDE(x); + } else if (!strcmp("fexpr~", s->s_name)) { + x = (t_expr *)pd_new(fexpr_tilde_class); + SET_FEXPR_TILDE(x); + } else { + post("expr_new: bad object name '%s'", s->s_name); + /* assume expr */ + x = (t_expr *)pd_new(expr_class); + SET_EXPR(x); + } +#else /* MSP */ + /* for now assume an expr~ */ + x = (t_expr *)pd_new(expr_tilde_class); + SET_EXPR_TILDE(x); +#endif + + /* + * initialize the newly allocated object + */ + x->exp_proxy = 0; + x->exp_nivec = 0; + x->exp_nexpr = 0; + x->exp_error = 0; + for (i = 0; i < MAX_VARS; i++) { + x->exp_stack[i] = (struct ex_ex *)0; + x->exp_outlet[i] = (t_outlet *)0; + x->exp_res[i].ex_type = 0; + x->exp_res[i].ex_int = 0; + x->exp_p_res[i] = (t_float *)0; + x->exp_var[i].ex_type = 0; + x->exp_var[i].ex_int = 0; + x->exp_p_var[i] = (t_float *)0; + x->exp_tmpres[i] = (t_float *)0; + x->exp_vsize = 0; + } + x->exp_f = 0; /* save the control value to be transformed to signal */ + + + if (expr_donew(x, ac, av)) + { + pd_error(x, "expr: syntax error"); +/* +SDY the following coredumps why? + pd_free(&x->exp_ob.ob_pd); +*/ + return (0); + } + + ninlet = 1; + for (i = 0, eptr = x->exp_var; i < MAX_VARS ; i++, eptr++) + if (eptr->ex_type) { + ninlet = i + 1; + } + + /* + * create the new inlets + */ + for (i = 1, eptr = x->exp_var + 1, dsp_index=1; iex_type) + { + case 0: + /* nothing is using this inlet */ + if (i < ninlet) +#ifdef PD + floatinlet_new(&x->exp_ob, &eptr->ex_flt); +#else /* MSP */ + inlet_new(&x->exp_ob, "float"); +#endif + break; + + case ET_II: + case ET_FI: + p = exprproxy_new(x, i); +#ifdef PD + inlet_new(&x->exp_ob, &p->p_pd, &s_float, &s_float); +#else /* MSP */ + inlet_new(&x->exp_ob, "float"); +#endif + break; + + case ET_SI: +#ifdef PD + symbolinlet_new(&x->exp_ob, (t_symbol **)&eptr->ex_ptr); +#else /* MSP */ + inlet_new(&x->exp_ob, "symbol"); +#endif + break; + + case ET_XI: + case ET_VI: + if (!IS_EXPR(x)) { + dsp_index++; +#ifdef PD + inlet_new(&x->exp_ob, &x->exp_ob.ob_pd, + &s_signal, &s_signal); +#else /* MSP */ + inlet_new(&x->exp_ob, "signal"); +#endif + break; + } else + post("expr: internal error expr_new"); + default: + pd_error(x, "expr: bad type (%lx) inlet = %d\n", + eptr->ex_type, i + 1); + break; + } + } + if (IS_EXPR(x)) { + for (i = 0; i < x->exp_nexpr; i++) + x->exp_outlet[i] = outlet_new(&x->exp_ob, 0); + } else { + for (i = 0; i < x->exp_nexpr; i++) + x->exp_outlet[i] = outlet_new(&x->exp_ob, + gensym("signal")); + x->exp_nivec = dsp_index; + } + /* + * for now assume a 64 sample size block but this may change once + * expr_dsp is called + */ + x->exp_vsize = 64; + for (i = 0; i < x->exp_nexpr; i++) { + x->exp_p_res[i] = fts_calloc(x->exp_vsize, sizeof (t_float)); + x->exp_tmpres[i] = fts_calloc(x->exp_vsize, sizeof (t_float)); + } + for (i = 0; i < MAX_VARS; i++) + x->exp_p_var[i] = fts_calloc(x->exp_vsize, sizeof (t_float)); + + return (x); +} + +t_int * +expr_perform(t_int *w) +{ + int i, j; + t_expr *x = (t_expr *)w[1]; + struct ex_ex res; + int n; + + /* sanity check */ + if (IS_EXPR(x)) { + post("expr_perform: bad x->exp_flags = %d", x->exp_flags); + abort(); + } + + if (x->exp_flags & EF_STOP) { + for (i = 0; i < x->exp_nexpr; i++) + memset(x->exp_res[i].ex_vec, 0, + x->exp_vsize * sizeof (t_float)); + return (w + 2); + } + + if (IS_EXPR_TILDE(x)) { + /* + * if we have only one expression, we can right on + * on the output directly, otherwise we have to copy + * the data because, outputs could be the same buffer as + * inputs + */ + if ( x->exp_nexpr == 1) + ex_eval(x, x->exp_stack[0], &x->exp_res[0], 0); + else { + res.ex_type = ET_VEC; + for (i = 0; i < x->exp_nexpr; i++) { + res.ex_vec = x->exp_tmpres[i]; + ex_eval(x, x->exp_stack[i], &res, 0); + } + n = x->exp_vsize * sizeof(t_float); + for (i = 0; i < x->exp_nexpr; i++) + memcpy(x->exp_res[i].ex_vec, x->exp_tmpres[i], + n); + } + return (w + 2); + } + + if (!IS_FEXPR_TILDE(x)) { + post("expr_perform: bad x->exp_flags = %d - expecting fexpr", + x->exp_flags); + return (w + 2); + } + /* + * since the output buffer could be the same as one of the inputs + * we need to keep the output in a different buffer + */ + for (i = 0; i < x->exp_vsize; i++) for (j = 0; j < x->exp_nexpr; j++) { + res.ex_type = 0; + res.ex_int = 0; + ex_eval(x, x->exp_stack[j], &res, i); + switch (res.ex_type) { + case ET_INT: + x->exp_tmpres[j][i] = (t_float) res.ex_int; + break; + case ET_FLT: + x->exp_tmpres[j][i] = res.ex_flt; + break; + default: + post("expr_perform: bad result type %d", res.ex_type); + } + } + /* + * copy inputs and results to the save buffers + * inputs need to be copied first as the output buffer can be + * same as an input buffer + */ + n = x->exp_vsize * sizeof(t_float); + for (i = 0; i < MAX_VARS; i++) + if (x->exp_var[i].ex_type == ET_XI) + memcpy(x->exp_p_var[i], x->exp_var[i].ex_vec, n); + for (i = 0; i < x->exp_nexpr; i++) { + memcpy(x->exp_p_res[i], x->exp_tmpres[i], n); + memcpy(x->exp_res[i].ex_vec, x->exp_tmpres[i], n); + } + return (w + 2); +} + +static void +expr_dsp(t_expr *x, t_signal **sp) +{ + int i, nv; + int newsize; + + x->exp_error = 0; /* reset all errors */ + newsize = (x->exp_vsize != sp[0]->s_n); + x->exp_vsize = sp[0]->s_n; /* record the vector size */ + for (i = 0; i < x->exp_nexpr; i++) { + x->exp_res[i].ex_type = ET_VEC; + x->exp_res[i].ex_vec = sp[x->exp_nivec + i]->s_vec; + } + for (i = 0, nv = 0; i < MAX_VARS; i++) + /* + * the first inlet is always a signal + * + * SDY We are warning the user till this limitation + * is taken away from pd + */ + if (!i || x->exp_var[i].ex_type == ET_VI || + x->exp_var[i].ex_type == ET_XI) { + if (nv >= x->exp_nivec) { + post("expr_dsp int. err nv = %d, x->exp_nive = %d", + nv, x->exp_nivec); + abort(); + } + x->exp_var[i].ex_vec = sp[nv]->s_vec; + nv++; + } + /* we always have one inlet but we may not use it */ + if (nv != x->exp_nivec && (nv != 0 || x->exp_nivec != 1)) { + post("expr_dsp internal error 2 nv = %d, x->exp_nive = %d", + nv, x->exp_nivec); + abort(); + } + + dsp_add(expr_perform, 1, (t_int *) x); + + /* + * The buffer are now being allocated for expr~ and fexpr~ + * because if we have more than one expression we need the + * temporary buffers, The save buffers are not really needed + if (!IS_FEXPR_TILDE(x)) + return; + */ + /* + * if we have already allocated the buffers and we have a + * new size free all the buffers + */ + if (x->exp_p_res[0]) { + if (!newsize) + return; + /* + * if new size, reallocate all the previous buffers for fexpr~ + */ + for (i = 0; i < x->exp_nexpr; i++) { + fts_free(x->exp_p_res[i]); + fts_free(x->exp_tmpres[i]); + } + for (i = 0; i < MAX_VARS; i++) + fts_free(x->exp_p_var[i]); + + } + for (i = 0; i < x->exp_nexpr; i++) { + x->exp_p_res[i] = fts_calloc(x->exp_vsize, sizeof (t_float)); + x->exp_tmpres[i] = fts_calloc(x->exp_vsize, sizeof (t_float)); + } + for (i = 0; i < MAX_VARS; i++) + x->exp_p_var[i] = fts_calloc(x->exp_vsize, sizeof (t_float)); +} + +/* + * expr_verbose -- toggle the verbose switch + */ +static void +expr_verbose(t_expr *x) +{ + if (x->exp_flags & EF_VERBOSE) { + x->exp_flags &= ~EF_VERBOSE; + post ("verbose off"); + } else { + x->exp_flags |= EF_VERBOSE; + post ("verbose on"); + } +} + + +static void +expr_version(t_expr *x) +{ + post( "expr, expr~, fexpr~ version %s", exp_version); +} + +/* + * expr_start -- turn on expr processing for now only used for fexpr~ + */ +static void +expr_start(t_expr *x) +{ + x->exp_flags &= ~EF_STOP; +} + +/* + * expr_stop -- turn on expr processing for now only used for fexpr~ + */ +static void +expr_stop(t_expr *x) +{ + x->exp_flags |= EF_STOP; +} +static void +fexpr_set_usage(void) +{ + post("fexpr~: set val ..."); + post("fexpr~: set {xy}[#] val ..."); +} + +/* + * fexpr_tilde_set -- set previous values of the buffers + * set val val ... - sets the first elements of output buffers + * set x val ... - sets the elements of the first input buffer + * set x# val ... - sets the elements of the #th input buffers + * set y val ... - sets the elements of the first output buffer + * set y# val ... - sets the elements of the #th output buffers + */ +static void +fexpr_tilde_set(t_expr *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *sx; + int vecno; + int i, nargs; + + if (!argc) + return; + sx = atom_getsymbolarg(0, argc, argv); + switch(sx->s_name[0]) { + case 'x': + if (!sx->s_name[1]) + vecno = 0; + else { + vecno = atoi(sx->s_name + 1); + if (!vecno) { + post("fexpr~.set: bad set x vector number"); + fexpr_set_usage(); + return; + } + if (vecno >= MAX_VARS) { + post("fexpr~.set: no more than %d inlets", + MAX_VARS); + return; + } + vecno--; + } + if (x->exp_var[vecno].ex_type != ET_XI) { + post("fexpr~-set: no signal at inlet %d", vecno + 1); + return; + } + nargs = argc - 1; + if (!nargs) { + post("fexpr~-set: no argument to set"); + return; + } + if (nargs > x->exp_vsize) { + post("fexpr~.set: %d set values larger than vector size(%d)", + nargs, x->exp_vsize); + post("fexpr~.set: only the first %d values will be set", + x->exp_vsize); + nargs = x->exp_vsize; + } + for (i = 0; i < nargs; i++) { + x->exp_p_var[vecno][x->exp_vsize - i - 1] = + atom_getfloatarg(i + 1, argc, argv); + } + return; + case 'y': + if (!sx->s_name[1]) + vecno = 0; + else { + vecno = atoi(sx->s_name + 1); + if (!vecno) { + post("fexpr~.set: bad set y vector number"); + fexpr_set_usage(); + return; + } + vecno--; + } + if (vecno >= x->exp_nexpr) { + post("fexpr~.set: only %d outlets", x->exp_nexpr); + return; + } + nargs = argc - 1; + if (!nargs) { + post("fexpr~-set: no argument to set"); + return; + } + if (nargs > x->exp_vsize) { + post("fexpr~-set: %d set values larger than vector size(%d)", + nargs, x->exp_vsize); + post("fexpr~.set: only the first %d values will be set", + x->exp_vsize); + nargs = x->exp_vsize; + } + for (i = 0; i < nargs; i++) { + x->exp_p_res[vecno][x->exp_vsize - i - 1] = + atom_getfloatarg(i + 1, argc, argv); + } + return; + case 0: + if (argc > x->exp_nexpr) { + post("fexpr~.set: only %d outlets available", + x->exp_nexpr); + post("fexpr~.set: the extra set values are ignored"); + } + for (i = 0; i < x->exp_nexpr && i < argc; i++) + x->exp_p_res[i][x->exp_vsize - 1] = + atom_getfloatarg(i, argc, argv); + return; + default: + fexpr_set_usage(); + return; + } + return; +} + +/* + * fexpr_tilde_clear - clear the past buffers + */ +static void +fexpr_tilde_clear(t_expr *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *sx; + int vecno; + int i, nargs; + + /* + * if no argument clear all input and output buffers + */ + if (!argc) { + for (i = 0; i < x->exp_nexpr; i++) + memset(x->exp_p_res[i], 0, x->exp_vsize*sizeof(t_float)); + for (i = 0; i < MAX_VARS; i++) + if (x->exp_var[i].ex_type == ET_XI) + memset(x->exp_p_var[i], 0, + x->exp_vsize*sizeof(t_float)); + return; + } + if (argc > 1) { + post("fexpr~ usage: 'clear' or 'clear {xy}[#]'"); + return; + } + + sx = atom_getsymbolarg(0, argc, argv); + switch(sx->s_name[0]) { + case 'x': + if (!sx->s_name[1]) + vecno = 0; + else { + vecno = atoi(sx->s_name + 1); + if (!vecno) { + post("fexpr~.clear: bad clear x vector number"); + return; + } + if (vecno >= MAX_VARS) { + post("fexpr~.clear: no more than %d inlets", + MAX_VARS); + return; + } + vecno--; + } + if (x->exp_var[vecno].ex_type != ET_XI) { + post("fexpr~-clear: no signal at inlet %d", vecno + 1); + return; + } + memset(x->exp_p_var[vecno], 0, x->exp_vsize*sizeof(t_float)); + return; + case 'y': + if (!sx->s_name[1]) + vecno = 0; + else { + vecno = atoi(sx->s_name + 1); + if (!vecno) { + post("fexpr~.clear: bad clear y vector number"); + return; + } + vecno--; + } + if (vecno >= x->exp_nexpr) { + post("fexpr~.clear: only %d outlets", x->exp_nexpr); + return; + } + memset(x->exp_p_res[vecno], 0, x->exp_vsize*sizeof(t_float)); + return; + return; + default: + post("fexpr~ usage: 'clear' or 'clear {xy}[#]'"); + return; + } + return; +} + +#ifdef PD + +void +expr_setup(void) +{ + /* + * expr initialization + */ + expr_class = class_new(gensym("expr"), (t_newmethod)expr_new, + (t_method)expr_ff, sizeof(t_expr), 0, A_GIMME, 0); + class_addlist(expr_class, expr_list); + exprproxy_class = class_new(gensym("exprproxy"), 0, + 0, sizeof(t_exprproxy), CLASS_PD, 0); + class_addfloat(exprproxy_class, exprproxy_float); + class_addmethod(expr_class,(t_method)expr_version, + gensym("version"), 0); + + /* + * expr~ initialization + */ + expr_tilde_class = class_new(gensym("expr~"), (t_newmethod)expr_new, + (t_method)expr_ff, sizeof(t_expr), 0, A_GIMME, 0); + class_addmethod(expr_tilde_class, nullfn, gensym("signal"), 0); + CLASS_MAINSIGNALIN(expr_tilde_class, t_expr, exp_f); + class_addmethod(expr_tilde_class,(t_method)expr_dsp, gensym("dsp"), + A_CANT, 0); + class_sethelpsymbol(expr_tilde_class, gensym("expr")); + class_addmethod(expr_tilde_class,(t_method)expr_version, + gensym("version"), 0); + /* + * fexpr~ initialization + */ + fexpr_tilde_class = class_new(gensym("fexpr~"), (t_newmethod)expr_new, + (t_method)expr_ff, sizeof(t_expr), 0, A_GIMME, 0); + class_addmethod(fexpr_tilde_class, nullfn, gensym("signal"), 0); + CLASS_MAINSIGNALIN(fexpr_tilde_class, t_expr, exp_f); + class_addmethod(fexpr_tilde_class,(t_method)expr_start, + gensym("start"), 0); + class_addmethod(fexpr_tilde_class,(t_method)expr_stop, + gensym("stop"), 0); + + class_addmethod(fexpr_tilde_class,(t_method)expr_dsp,gensym("dsp"), + A_CANT, 0); + class_addmethod(fexpr_tilde_class, (t_method)fexpr_tilde_set, + gensym("set"), A_GIMME, 0); + class_addmethod(fexpr_tilde_class, (t_method)fexpr_tilde_clear, + gensym("clear"), A_GIMME, 0); + class_addmethod(fexpr_tilde_class,(t_method)expr_verbose, + gensym("verbose"), 0); + class_addmethod(fexpr_tilde_class,(t_method)expr_version, + gensym("version"), 0); + class_sethelpsymbol(fexpr_tilde_class, gensym("expr")); + +} + +void +expr_tilde_setup(void) +{ + expr_setup(); +} + +void +fexpr_tilde_setup(void) +{ + expr_setup(); +} +#else /* MSP */ +void +main(void) +{ + setup((t_messlist **)&expr_tilde_class, (method)Nexpr_new, + (method)expr_ff, (short)sizeof(t_expr), 0L, A_GIMME, 0); + addmess((method)expr_dsp, "dsp", A_CANT, 0); // dsp method + dsp_initclass(); +} +#endif + + +/* -- the following functions use Pd internals and so are in the "if" file. */ + + +int +ex_getsym(char *p, fts_symbol_t *s) +{ + *s = gensym(p); + return (0); +} + +const char * +ex_symname(fts_symbol_t s) +{ + if (!s) + return (0); + return (fts_symbol_name(s)); +} + +/* + * max_ex_tab -- evaluate this table access + * eptr is the name of the table and arg is the index we + * have to put the result in optr + * return 1 on error and 0 otherwise + * + * Arguments: + * the expr object + * table + * the argument + * the result pointer + */ +int +max_ex_tab(struct expr *expr, fts_symbol_t s, struct ex_ex *arg, + struct ex_ex *optr) +{ +#ifdef PD + t_garray *garray; + int size; + long indx; + t_word *wvec; + + if (!s || !(garray = (t_garray *)pd_findbyclass(s, garray_class)) || + !garray_getfloatwords(garray, &size, &wvec)) + { + optr->ex_type = ET_FLT; + optr->ex_flt = 0; + pd_error(expr, "no such table '%s'", ex_symname(s)); + return (1); + } + optr->ex_type = ET_FLT; + + switch (arg->ex_type) { + case ET_INT: + indx = arg->ex_int; + break; + case ET_FLT: + /* strange interpolation code deleted here -msp */ + indx = arg->ex_flt; + break; + + default: /* do something with strings */ + pd_error(expr, "expr: bad argument for table '%s'\n", fts_symbol_name(s)); + indx = 0; + } + if (indx < 0) indx = 0; + else if (indx >= size) indx = size - 1; + optr->ex_flt = wvec[indx].w_float; +#else /* MSP */ + /* + * table lookup not done for MSP yet + */ + post("max_ex_tab: not complete for MSP yet!"); + optr->ex_type = ET_FLT; + optr->ex_flt = 0; +#endif + return (0); +} + +/* + * max_ex_tab_store -- store a value in a table + * tbl[arg->value] = rval.value + * eptr is the name of the table and arg is the index we + * have to put the result in optr + * return 1 on error and 0 otherwise + * + * Arguments: + * the expr object + * table + * the argument + * value to be stored + * the result pointer + */ +int +max_ex_tab_store(struct expr *expr, t_symbol *s, struct ex_ex *arg, + struct ex_ex *rval, struct ex_ex *optr) +{ +#ifdef PD + t_garray *garray; + int size; + long indx; + t_word *wvec; + + if (!s || !(garray = (t_garray *)pd_findbyclass(s, garray_class)) || + !garray_getfloatwords(garray, &size, &wvec)) { + optr->ex_type = ET_FLT; + optr->ex_flt = 0; + if (s) + pd_error(expr, "no such table to store '%s'", s->s_name); + else + pd_error(expr, "cannot store in unnamed table"); + return (1); + } + optr->ex_type = ET_FLT; + + switch (arg->ex_type) { + case ET_INT: + indx = arg->ex_int; + break; + case ET_FLT: + /* strange interpolation code deleted here -msp */ + indx = arg->ex_flt; + break; + + default: /* do something with strings */ + pd_error(expr, "expr: bad argument for table store '%s'\n", + fts_symbol_name(s)); + indx = 0; + } + if (indx < 0) + indx = 0; + else if (indx >= size) + indx = size - 1; + *optr = *rval; + switch (rval->ex_type) { + case ET_INT: + wvec[indx].w_float = rval->ex_int; + break; + case ET_FLT: + wvec[indx].w_float = rval->ex_flt; + break; + default: + pd_error(expr, "expr:bad right value type '%ld'", rval->ex_type); + optr->ex_type = ET_FLT; + optr->ex_flt = 0; + return (1); + } + garray_redraw(garray); + return(0); + +#else /* MSP */ + /* + * table lookup not done for MSP yet + */ + post("max_ex_tab: not complete for MSP yet!"); + optr->ex_type = ET_FLT; + optr->ex_flt = 0; +#endif + return (0); +} + +int +max_ex_var(struct expr *expr, t_symbol *var, struct ex_ex *optr, int idx) +{ + optr->ex_type = ET_FLT; + if (!strcmp(var->s_name, "sys_idx")) { + optr->ex_flt = idx; + return (0); + } + if (value_getfloat(var, &(optr->ex_flt))) { + optr->ex_type = ET_FLT; + optr->ex_flt = 0; + pd_error(expr, "no such var '%s'", var->s_name); + return (1); + } + return (0); +} + +#ifdef PD /* this goes to the end of this file as the following functions + * should be defined in the expr object in MSP + */ +#define ISTABLE(sym, garray, size, vec) \ +if (!sym || !(garray = (t_garray *)pd_findbyclass(sym, garray_class)) || \ + !garray_getfloatwords(garray, &size, &vec)) { \ + optr->ex_type = ET_FLT; \ + optr->ex_int = 0; \ + error("no such table '%s'", sym?(sym->s_name):"(null)"); \ + return; \ +} + +/* + * ex_size -- find the size of a table + */ +void +ex_size(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + t_symbol *s; + t_garray *garray; + int size; + t_word *wvec; + + if (argv->ex_type != ET_SYM) + { + post("expr: size: need a table name\n"); + optr->ex_type = ET_INT; + optr->ex_int = 0; + return; + } + + s = (fts_symbol_t ) argv->ex_ptr; + + ISTABLE(s, garray, size, wvec); + + optr->ex_type = ET_INT; + optr->ex_int = size; +} + +/* + * ex_sum -- calculate the sum of all elements of a table + */ + +void +ex_sum(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + t_symbol *s; + t_garray *garray; + int size; + t_word *wvec; + t_float sum; + int indx; + + if (argv->ex_type != ET_SYM) + { + post("expr: sum: need a table name\n"); + optr->ex_type = ET_INT; + optr->ex_int = 0; + return; + } + + s = (fts_symbol_t ) argv->ex_ptr; + + ISTABLE(s, garray, size, wvec); + + for (indx = 0, sum = 0; indx < size; indx++) + sum += wvec[indx].w_float; + + optr->ex_type = ET_FLT; + optr->ex_flt = sum; +} + + +/* + * ex_Sum -- calculate the sum of table with the given boundaries + */ + +void +ex_Sum(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + t_symbol *s; + t_garray *garray; + int size; + t_word *wvec; + t_float sum; + long indx, n1, n2; + + if (argv->ex_type != ET_SYM) + { + post("expr: sum: need a table name\n"); + optr->ex_type = ET_INT; + optr->ex_int = 0; + return; + } + + s = (fts_symbol_t ) argv->ex_ptr; + + ISTABLE(s, garray, size, wvec); + + switch((++argv)->ex_type) { + case ET_INT: + n1 = argv->ex_int; + break; + case ET_FLT: + n1 = argv->ex_flt; + break; + default: + post("expr: Sum: boundaries have to be fix values\n"); + optr->ex_type = ET_INT; + optr->ex_int = 0; + return; + } + if (n1 < 0) + n1 = 0; + + switch((++argv)->ex_type) { + case ET_INT: + n2 = argv->ex_int; + break; + case ET_FLT: + n2 = argv->ex_flt; + break; + default: + post("expr: Sum: boundaries have to be fix values\n"); + optr->ex_type = ET_INT; + optr->ex_int = 0; + return; + } + if (n2 > size) + n2 = size; + + for (indx = n1, sum = 0; indx <= n2; indx++) + if (indx >= 0 && indx < size) + sum += wvec[indx].w_float; + + optr->ex_type = ET_FLT; + optr->ex_flt = sum; +} + +/* + * ex_avg -- calculate the avarage of a table + */ + +void +ex_avg(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + t_symbol *s; + t_garray *garray; + int size; + t_word *wvec; + t_float sum; + int indx; + + if (argv->ex_type != ET_SYM) + { + post("expr: avg: need a table name\n"); + optr->ex_type = ET_INT; + optr->ex_int = 0; + return; + } + + s = (fts_symbol_t ) argv->ex_ptr; + + ISTABLE(s, garray, size, wvec); + + for (indx = 0, sum = 0; indx < size; indx++) + sum += wvec[indx].w_float; + + optr->ex_type = ET_FLT; + optr->ex_flt = sum / size; +} + + +/* + * ex_Avg -- calculate the avarage of table with the given boundaries + */ + +void +ex_Avg(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + t_symbol *s; + t_garray *garray; + int size; + t_word *wvec; + t_float sum; + long indx, n1, n2; + + if (argv->ex_type != ET_SYM) + { + post("expr: sum: need a table name\n"); + optr->ex_type = ET_INT; + optr->ex_int = 0; + return; + } + + s = (fts_symbol_t ) argv->ex_ptr; + + ISTABLE(s, garray, size, wvec); + + switch((++argv)->ex_type) { + case ET_INT: + n1 = argv->ex_int; + break; + case ET_FLT: + n1 = argv->ex_flt; + break; + default: + post("expr: Avg: boundaries have to be fix values\n"); + optr->ex_type = ET_INT; + optr->ex_int = 0; + return; + } + if (n1 < 0) + n1 = 0; + + switch((++argv)->ex_type) { + case ET_INT: + n2 = argv->ex_int; + break; + case ET_FLT: + n2 = argv->ex_flt; + break; + default: + post("expr: Avg: boundaries have to be fix values\n"); + optr->ex_type = ET_INT; + optr->ex_int = 0; + return; + } + if (n2 >= size) + n2 = size - 1; + + for (indx = n1, sum = 0; indx <= n2; indx++) + if (indx >= 0 && indx < size) + sum += wvec[indx].w_float; + + optr->ex_type = ET_FLT; + optr->ex_flt = sum / (n2 - n1 + 1); +} + +/* + * max_ex_store --- store a value in a variable or table + */ +int +max_ex_var_store(struct expr *expr, t_symbol * var, struct ex_ex *eptr, struct ex_ex *optr) +{ + t_float value = 0.; + + *optr = *eptr; + switch (eptr->ex_type) { + case ET_INT: + value = eptr->ex_int; + break; + case ET_FLT: + value = eptr->ex_flt; + break; + default: + post("do not know yet\n"); + } + + if (value_setfloat(var, value)) { + optr->ex_flt = 0; + pd_error(expr, "no such var '%s'", var->s_name); + return (1); + } + return (0); +} + +/* + * ex_store -- store a value in a table + * if the index is greater the size of the table, + * we will make a modulo the size of the table + */ + +void +ex_store(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ +/* SDY - look into this function */ +#if 0 + fts_symbol_t s; + fts_integer_vector_t *tw = 0; + + if (argv->ex_type != ET_SYM) + { + post("expr: store: need a table name\n"); + } + + s = (fts_symbol_t ) (argv++)->ex_ptr; + + tw = table_integer_vector_get_by_name(s); + + if (! tw) + { + optr->ex_type = ET_INT; + optr->ex_int = 0; + post("expr: store: no such table %s\n", fts_symbol_name(s)); + return; + } + + if (argv->ex_type != ET_INT || argv[1].ex_type != ET_INT) + { + post("expr: store: arguments have to be integer\n"); + optr->ex_type = ET_INT; + optr->ex_int = 0; + } + + fts_integer_vector_set_element(tw, argv->ex_int < 0 ? 0 : argv->ex_int % fts_integer_vector_get_size(tw), argv[1].ex_int); + *optr = argv[1]; +#endif +} + +#else /* MSP */ + +void +pd_error(void *object, char *fmt, ...) +{ + va_list ap; + t_int arg[8]; + int i; + static int saidit = 0; + va_start(ap, fmt); +/* SDY + vsprintf(error_string, fmt, ap); +*/ post(fmt, ap); + va_end(ap); +/* SDY + fprintf(stderr, "error: %s\n", error_string); + error_object = object; +*/ + if (!saidit) + { + post("... you might be able to track this down from the Find menu."); + saidit = 1; + } +} +#endif diff --git a/ports/camomile/source/Pd/PdArray.cpp b/ports/camomile/source/Pd/PdArray.cpp new file mode 100644 index 00000000..3dc3b8d7 --- /dev/null +++ b/ports/camomile/source/Pd/PdArray.cpp @@ -0,0 +1,79 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + +#include "PdArray.hpp" + +extern "C" +{ +#include "x_libpd_extra_utils.h" +} + +namespace pd +{ + // ==================================================================================== // + // GRAPH // + // ==================================================================================== // + + Array::Array(std::string const& name, void* instance) : + m_name(name), m_instance(instance) + { + ; + } + + std::string Array::getName() const noexcept + { + return m_name; + } + + bool Array::isDrawingPoints() const noexcept + { + libpd_set_instance(static_cast(m_instance)); + return libpd_array_get_style(m_name.c_str()) == 0; + } + + bool Array::isDrawingLine() const noexcept + { + libpd_set_instance(static_cast(m_instance)); + return libpd_array_get_style(m_name.c_str()) == 1; + } + + bool Array::isDrawingCurve() const noexcept + { + libpd_set_instance(static_cast(m_instance)); + return libpd_array_get_style(m_name.c_str()) == 2; + } + + std::array Array::getScale() const noexcept + { + float min = -1, max = 1; + libpd_set_instance(static_cast(m_instance)); + libpd_array_get_scale(m_name.c_str(), &min, &max); + return {min, max}; + } + + void Array::read(std::vector& output) const + { + libpd_set_instance(static_cast(m_instance)); + int const size = libpd_arraysize(m_name.c_str()); + output.resize(static_cast(size)); + libpd_read_array(output.data(), m_name.c_str(), 0, size); + } + + void Array::write(std::vector const& input) + { + libpd_set_instance(static_cast(m_instance)); + libpd_write_array(m_name.c_str(), 0, input.data(), static_cast(input.size())); + } + + void Array::write(const size_t pos, float const input) + { + libpd_set_instance(static_cast(m_instance)); + libpd_write_array(m_name.c_str(), static_cast(pos), &input, 1); + } +} + + + diff --git a/ports/camomile/source/Pd/PdArray.hpp b/ports/camomile/source/Pd/PdArray.hpp new file mode 100755 index 00000000..8fcda79d --- /dev/null +++ b/ports/camomile/source/Pd/PdArray.hpp @@ -0,0 +1,72 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ +#pragma once + +#include +#include +#include +#include + +namespace pd +{ + class Instance; + class Gui; + // ==================================================================================== // + // GRAPH // + // ==================================================================================== // + + //! @brief The Pd array. + //! @details The class is a wrapper around a Pd array. The lifetime of the internal array\n + //! is not guaranteed by the class. + //! @see Instance, Gui + class Array + { + public: + + //! @brief The default constructor. + Array() = default; + + //! @brief The copy operator. + Array(Array const& other) = default; + + //! @brief The destructor. + ~Array() noexcept = default; + + //! @brief Gets the name of the array. + std::string getName() const noexcept; + + //! @brief Gets id it should be drawn as points. + bool isDrawingPoints() const noexcept; + + //! @brief Gets id it should be drawn as lines. + bool isDrawingLine() const noexcept; + + //! @brief Gets id it should be drawn as curves. + bool isDrawingCurve() const noexcept; + + //! @brief Gets the scale of the array. + std::array getScale() const noexcept; + + //! @brief Gets the values of the array. + void read(std::vector& output) const; + + //! @brief Writes the values of the array. + void write(std::vector const& input); + + //! @brief Writes a value of the array. + void write(const size_t pos, float const input); + private: + + Array(std::string const& name, void* instance); + + std::string m_name = std::string(""); + void* m_instance = nullptr; + + friend class Instance; + friend class Gui; + }; +} + diff --git a/ports/camomile/source/Pd/PdAtom.hpp b/ports/camomile/source/Pd/PdAtom.hpp new file mode 100644 index 00000000..342e24f4 --- /dev/null +++ b/ports/camomile/source/Pd/PdAtom.hpp @@ -0,0 +1,61 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + +#pragma once + +namespace pd +{ + // ==================================================================================== // + // ATOM // + // ==================================================================================== // + + //! @brief The Pd atom. + //! @details The class is a copy of the Pd atom. + //! @see Instance, Gui + class Atom + { + public: + //! @brief The default constructor. + inline Atom() : type(FLOAT), value(0), symbol() {} + + //! @brief The float constructor. + inline Atom(const float val) : type(FLOAT), value(val), symbol() {} + + //! @brief The string constructor. + inline Atom(const std::string& sym) : type(SYMBOL), value(0), symbol(sym) {} + + //! @brief The c-string constructor. + inline Atom(const char* sym) : type(SYMBOL), value(0), symbol(sym) {} + + //! @brief Check if the atom is a float. + inline bool isFloat() const noexcept { return type == FLOAT; } + + //! @brief Check if the atom is a string. + inline bool isSymbol() const noexcept { return type == SYMBOL; } + + //! @brief Get the float value. + inline float getFloat() const noexcept { return value; } + + //! @brief Get the string. + inline std::string const& getSymbol() const noexcept { return symbol; } + + //! @brief Compare two atoms. + inline bool operator==(Atom const& other) const noexcept + { + if(type == SYMBOL) { return other.type == SYMBOL && symbol == other.symbol; } + else { return other.type == FLOAT && value == other.value; } + } + private: + enum Type + { + FLOAT, + SYMBOL + }; + Type type = FLOAT; + float value = 0; + std::string symbol; + }; +} diff --git a/ports/camomile/source/Pd/PdGui.cpp b/ports/camomile/source/Pd/PdGui.cpp new file mode 100755 index 00000000..677c21d3 --- /dev/null +++ b/ports/camomile/source/Pd/PdGui.cpp @@ -0,0 +1,502 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + +#include "PdGui.hpp" +#include "PdInstance.hpp" +#include +#include + +extern "C" +{ +#include +#include +#include +#include +#include +#include "x_libpd_extra_utils.h" +} + +namespace pd +{ + // ==================================================================================== // + // GUI // + // ==================================================================================== // + + // False GATOM + typedef struct _fake_gatom + { + t_text a_text; + t_atom a_atom; + t_glist* a_glist; + t_float a_toggle; + t_float a_draghi; + t_float a_draglo; + t_symbol *a_label; + t_symbol *a_symfrom; + t_symbol *a_symto; + char a_buf[40]; + char a_shift; + char a_wherelabel; // 0-3 for left, right, above, below + t_symbol *a_expanded_to; + } t_fake_gatom; + + + Gui::Gui(void* ptr, void* patch, Instance* instance) noexcept : + Object(ptr, patch, instance), m_type(Type::Undefined) + { + const std::string name = getName(); + if(name == "bng") + { + m_type = Type::Bang; + } + else if(name == "hsl") + { + m_type = Type::HorizontalSlider; + } + else if(name == "vsl") + { + m_type = Type::VerticalSlider; + } + else if(name == "tgl") + { + m_type = Type::Toggle; + } + else if(name == "nbx") + { + m_type = Type::Number; + } + else if(name == "vradio") + { + m_type = Type::VerticalRadio; + } + else if(name == "hradio") + { + m_type = Type::HorizontalRadio; + } + else if(name == "cnv") + { + m_type = Type::Panel; + } + else if(name == "vu") + { + m_type = Type::VuMeter; + } + else if(name == "text") + { + m_type = Type::Comment; + } + else if(name == "gatom") + { + if(static_cast(m_ptr)->a_atom.a_type == A_FLOAT) + m_type = Type::AtomNumber; + else if(static_cast(m_ptr)->a_atom.a_type == A_SYMBOL) + m_type = Type::AtomSymbol; + } + else if(name == "canvas") + { + if(static_cast(m_ptr)->gl_list) + { + t_class* c = static_cast(m_ptr)->gl_list->g_pd; + if(c && c->c_name && std::string(c->c_name->s_name) == std::string("array")) + { + m_type = Type::Array; + } + } + if(m_type != Type::Array && static_cast(m_ptr)->gl_isgraph) + { + m_type = Type::GraphOnParent; + canvas_vis(static_cast(m_ptr), 1.f); + } + } + } + + size_t Gui::getNumberOfSteps() const noexcept + { + if(!m_ptr) + return 0.f; + if(m_type == Type::Toggle) + { + return 2; + } + else if(m_type == Type::HorizontalRadio) + { + return (static_cast(m_ptr))->x_number - 1; + } + else if(m_type == Type::VerticalRadio) + { + return (static_cast(m_ptr))->x_number; + } + else if(m_type == Type::AtomNumber) + { + return static_cast(m_ptr)->te_width == 1; + } + return 0.f; + } + + float Gui::getMinimum() const noexcept + { + if(!m_ptr) + return 0.f; + if(m_type == Type::HorizontalSlider) + { + return (static_cast(m_ptr))->x_min; + } + else if(m_type == Type::VerticalSlider) + { + return (static_cast(m_ptr))->x_min; + } + else if(m_type == Type::Number) + { + return (static_cast(m_ptr))->x_min; + } + else if(m_type == Type::AtomNumber) + { + t_fake_gatom const* gatom = static_cast(m_ptr); + if(std::abs(gatom->a_draglo) > std::numeric_limits::epsilon() && + std::abs(gatom->a_draghi) > std::numeric_limits::epsilon()) + { + return gatom->a_draglo; + } + return -std::numeric_limits::max(); + } + return 0.f; + } + + float Gui::getMaximum() const noexcept + { + if(!m_ptr) + return 1.f; + if(m_type == Type::HorizontalSlider) + { + return (static_cast(m_ptr))->x_max; + } + else if(m_type == Type::VerticalSlider) + { + return (static_cast(m_ptr))->x_max; + } + else if(m_type == Type::Number) + { + return (static_cast(m_ptr))->x_max; + } + else if(m_type == Type::HorizontalRadio) + { + return (static_cast(m_ptr))->x_number - 1; + } + else if(m_type == Type::VerticalRadio) + { + return (static_cast(m_ptr))->x_number - 1; + } + else if(m_type == Type::Bang) + { + return 1; + } + else if(m_type == Type::AtomNumber) + { + t_fake_gatom const* gatom = static_cast(m_ptr); + if(std::abs(gatom->a_draglo) > std::numeric_limits::epsilon() && + std::abs(gatom->a_draghi) > std::numeric_limits::epsilon()) + { + return gatom->a_draghi; + } + return std::numeric_limits::max(); + } + return 1.f; + } + + float Gui::getValue() const noexcept + { + if(!m_ptr) + return 0.f; + if(m_type == Type::HorizontalSlider) + { + return (static_cast(m_ptr))->x_fval; + } + else if(m_type == Type::VerticalSlider) + { + return (static_cast(m_ptr))->x_fval; + } + else if(m_type == Type::Toggle) + { + return (static_cast(m_ptr))->x_on; + } + else if(m_type == Type::Number) + { + return (static_cast(m_ptr))->x_val; + } + else if(m_type == Type::HorizontalRadio) + { + return (static_cast(m_ptr))->x_on; + } + else if(m_type == Type::VerticalRadio) + { + return (static_cast(m_ptr))->x_on; + } + else if(m_type == Type::Bang) + { + return (static_cast(m_ptr))->x_flashed; + } + else if(m_type == Type::VuMeter) + { + return 0; + } + else if(m_type == Type::AtomNumber) + { + return atom_getfloat(&(static_cast(m_ptr)->a_atom)); + } + return 0.f; + } + + void Gui::setValue(float value) noexcept + { + if(!m_ptr || m_type == Type::Comment || m_type == Type::AtomSymbol) + return; + m_instance->enqueueDirectMessages(m_ptr, value); + + } + + bool Gui::jumpOnClick() const noexcept + { + if(!m_ptr) + return 0.f; + if(m_type == Type::HorizontalSlider) + { + return (static_cast(m_ptr))->x_steady == 0; + } + else if(m_type == Type::VerticalSlider) + { + return (static_cast(m_ptr))->x_steady == 0; + } + return false; + } + + bool Gui::isLogScale() const noexcept + { + if(!m_ptr) + return 0.f; + if(m_type == Type::HorizontalSlider) + { + return (static_cast(m_ptr))->x_lin0_log1 != 0; + } + else if(m_type == Type::VerticalSlider) + { + return (static_cast(m_ptr))->x_lin0_log1 != 0; + } + return false; + } + + std::string Gui::getSymbol() const noexcept + { + if(!m_ptr || m_type != Type::AtomSymbol) + return std::string(); + else + { + m_instance->setThis(); + return atom_getsymbol(&(static_cast(m_ptr)->a_atom))->s_name; + } + } + + void Gui::setSymbol(std::string const& value) noexcept + { + if(!m_ptr || m_type != Type::AtomSymbol) + return; + m_instance->enqueueDirectMessages(m_ptr, value); + } + + float Gui::getFontHeight() const noexcept + { + if(!m_ptr ) + return 0; + if(isIEM()) + { + return static_cast((static_cast(m_ptr))->x_fontsize); + } + else + { + return libpd_get_canvas_font_height(static_cast(m_patch)); + } + } + + std::string Gui::getFontName() const + { + if(!m_ptr ) + return std::string(sys_font); + if(isIEM()) + { + return std::string((static_cast(m_ptr))->x_font); + } + else + { + return std::string(sys_font); + } + } + + static unsigned int fromIemColors(int const color) + { + unsigned int const c = static_cast(color << 8 | 0xFF); + return ((0xFF << 24) | ((c >> 24) << 16) | ((c >> 16) << 8) | (c >> 8)); + } + + unsigned int Gui::getBackgroundColor() const noexcept + { + if(m_ptr && isIEM()) + { + return libpd_iemgui_get_background_color(m_ptr); + } + return 0xffffffff; + } + + unsigned int Gui::getForegroundColor() const noexcept + { + if(m_ptr && isIEM()) + { + return libpd_iemgui_get_foreground_color(m_ptr); + } + return 0xff000000; + } + + std::array Gui::getBounds() const noexcept + { + if(m_type == Type::Panel) + { + std::array const bounds = Object::getBounds(); + return {bounds[0], bounds[1], + static_cast(m_ptr)->x_vis_w + 1, + static_cast(m_ptr)->x_vis_h + 1}; + } + else if(m_type == Type::AtomNumber || m_type == Type::AtomSymbol) + { + std::array const bounds = Object::getBounds(); + return {bounds[0], bounds[1], bounds[2], bounds[3] - 2}; + } + else if(m_type == Type::Comment) + { + std::array const bounds = Object::getBounds(); + return {bounds[0] + 2, bounds[1] + 2, bounds[2], bounds[3] - 2}; + } + return Object::getBounds(); + } + + Array Gui::getArray() const noexcept + { + if(m_type == Type::Array) + { + return m_instance->getArray(libpd_array_get_name(static_cast(m_ptr)->gl_list)); + } + return Array(); + } + + Patch Gui::getPatch() const noexcept + { + if(m_type == Type::GraphOnParent) + { + return Patch(m_ptr, m_instance); + } + return Patch(); + } + + // ==================================================================================== // + // LABEL // + // ==================================================================================== // + + Label Gui::getLabel() const noexcept + { + m_instance->setThis(); + if(isIEM()) + { + t_symbol const* sym = canvas_realizedollar(static_cast(m_ptr)->x_glist, static_cast(m_ptr)->x_lab); + if(sym) + { + auto const text = std::string(sym->s_name); + if(!text.empty() && text != std::string("empty")) + { + auto const* iemgui = static_cast(m_ptr); + auto const color = fromIemColors(iemgui->x_lcol); + auto const bounds = getBounds(); + auto const posx = bounds[0] + iemgui->x_ldx; + auto const posy = bounds[1] + iemgui->x_ldy; + auto const fontname = getFontName(); + auto const fontheight = getFontHeight(); + return Label(text, color, posx, posy, fontname, fontheight); + } + } + } + else if(isAtom()) + { + t_symbol const* sym = canvas_realizedollar(static_cast(m_ptr)->a_glist, static_cast(m_ptr)->a_label); + if(sym) + { + auto const text = std::string(sym->s_name); + auto const bounds = getBounds(); + auto const* gatom = static_cast(m_ptr); + auto const color = 0xff000000; + auto const fontname = getFontName(); + auto const fontheight = sys_hostfontsize(glist_getfont(static_cast(m_patch)), glist_getzoom(static_cast(m_patch))); + + if (gatom->a_wherelabel == 0) // Left + { + auto const nchars = static_cast(text.size()); + auto const fwidth = glist_fontwidth(static_cast(m_ptr)->a_glist); + auto const posx = bounds[0] - 4 - nchars * fwidth; + auto const posy = bounds[1] + 2 + fontheight / 2; + return Label(text, color,posx, posy, fontname, fontheight); + } + else if (gatom->a_wherelabel == 1) // Right + { + auto const posx = bounds[0] + bounds[2] + 2; + auto const posy = bounds[1] + 2 + fontheight / 2; + return Label(text, color, posx, posy, fontname, fontheight); + } + else if (gatom->a_wherelabel == 2) // Up + { + auto const posx = bounds[0] - 1; + auto const posy = bounds[1] - 1 - fontheight / 2; + return Label(text, color, posx, posy, fontname, fontheight); + } + auto const posx = bounds[0] - 1; + auto const posy = bounds[1] + bounds[3] + 2 + fontheight / 2; + return Label(text, color, posx, posy, fontname, fontheight); // Down + } + } + return Label(); + } + + Label::Label() noexcept : + m_text(""), + m_color(0xff000000), + m_position({0, 0}) + { + } + + Label::Label(Label const& other) noexcept : + m_text(other.m_text), + m_color(other.m_color), + m_position(other.m_position) + { + } + + Label::Label(std::string const& text, unsigned int color, int x, int y, std::string const& fontname, float fontheight) noexcept : + m_text(text), + m_color(color), + m_position({x, y}), + m_font_name(fontname), + m_font_height(fontheight) + { + + } + + float Label::getFontHeight() const noexcept + { + return m_font_height; + } + + std::string Label::getFontName() const + { + return m_font_name; + } +} + + + diff --git a/ports/camomile/source/Pd/PdGui.hpp b/ports/camomile/source/Pd/PdGui.hpp new file mode 100755 index 00000000..90ba5a68 --- /dev/null +++ b/ports/camomile/source/Pd/PdGui.hpp @@ -0,0 +1,149 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ +#pragma once + +#include "PdObject.hpp" +#include "PdArray.hpp" + +namespace pd +{ + class Label; + + // ==================================================================================== // + // GUI // + // ==================================================================================== // + + //! @brief The Pd GUI objects. + //! @details The Instance is a wrapper for the Pd native GUI. The lifetime of the internal\n + //! GUI is not guaranteed by the class. + //! @see Instance, Patch, Object + class Gui : public Object + { + public: + //! @brief The type of GUI. + enum class Type : size_t + { + Undefined = 0, + HorizontalSlider = 1, + VerticalSlider = 2, + Toggle = 3, + Number = 4, + HorizontalRadio = 5, + VerticalRadio = 6, + Bang = 7, + Panel = 8, + VuMeter = 9, + Comment = 10, + AtomNumber = 11, + AtomSymbol = 12, + Array = 13, + GraphOnParent = 14 + }; + + //! @brief The default constructor + Gui() noexcept = default; + + //! @brief The copy constructor. + Gui(const Gui& other) noexcept = default; + + //! @brief The copy operator. + Gui& operator=(Gui const& other) noexcept = default; + + //! @brief The destructor. + ~Gui() noexcept = default; + + //! @brief The type of the GUI. + inline Type getType() const noexcept + { + return m_type; + } + + //! @brief If the GUI is an IEM's GUI. + bool isIEM() const noexcept + { + return (m_type != Type::Undefined) && (m_type < Type::Comment); + } + + //! @brief If the GUI is an Atom GUI (AtomNumber or AtomSymbol). + bool isAtom() const noexcept + { + return (m_type == Type::AtomNumber) || (m_type == Type::AtomSymbol); + } + + //! @brief Get the font height. + float getFontHeight() const noexcept; + + //! @brief Get the font name. + std::string getFontName() const; + + float getMinimum() const noexcept; + + float getMaximum() const noexcept; + + float getValue() const noexcept; + + void setValue(float value) noexcept; + + size_t getNumberOfSteps() const noexcept; + + unsigned int getBackgroundColor() const noexcept; + + unsigned int getForegroundColor() const noexcept; + + std::string getSymbol() const noexcept; + + void setSymbol(std::string const& value) noexcept; + + std::array getBounds() const noexcept override; + + bool jumpOnClick() const noexcept; + + bool isLogScale() const noexcept; + + Array getArray() const noexcept; + + Label getLabel() const noexcept; + + Patch getPatch() const noexcept; + private: + + Gui(void* ptr, void* patch, Instance* instance) noexcept; + + Type m_type = Type::Undefined; + friend class Patch; + }; + + // ==================================================================================== // + // LABEL // + // ==================================================================================== // + + class Label + { + public: + Label() noexcept; + Label(Label const& other) noexcept; + Label(std::string const& text, unsigned int color, int x, int y, std::string const& fontname, float fontheight) noexcept; + + std::string getText() const noexcept { return m_text; } + unsigned int getColor() const noexcept { return m_color; } + std::array getPosition() const noexcept { return m_position; } + + //! @brief Get the font height. + float getFontHeight() const noexcept; + + //! @brief Get the font name. + std::string getFontName() const; + private: + Label(Gui const& gui) noexcept; + std::string const m_text; + unsigned int const m_color; + std::array const m_position; + std::string m_font_name; + float m_font_height; + friend class Gui; + }; +} + diff --git a/ports/camomile/source/Pd/PdInstance.cpp b/ports/camomile/source/Pd/PdInstance.cpp new file mode 100644 index 00000000..a5e308f4 --- /dev/null +++ b/ports/camomile/source/Pd/PdInstance.cpp @@ -0,0 +1,446 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + + +#include + +extern "C" +{ +#include +#include "x_libpd_multi.h" +#include "x_libpd_extra_utils.h" +} + +#include "PdInstance.hpp" +#include "PdPatch.hpp" + +extern "C" +{ + struct pd::Instance::internal + { + static void instance_multi_bang(pd::Instance* ptr, const char *recv) + { + ptr->m_message_queue.try_enqueue({std::string("bang")}); + } + + static void instance_multi_float(pd::Instance* ptr, const char *recv, float f) + { + ptr->m_message_queue.try_enqueue({std::string("float"), std::vector(1, f)}); + } + + static void instance_multi_symbol(pd::Instance* ptr, const char *recv, const char *sym) + { + ptr->m_message_queue.try_enqueue({std::string("symbol"), std::vector(1, std::string(sym))}); + } + + static void instance_multi_list(pd::Instance* ptr, const char *recv, int argc, t_atom *argv) + { + Message mess{std::string("list"), std::vector(argc)}; + for(int i = 0; i < argc; ++i) + { + if(argv[i].a_type == A_FLOAT) + mess.list[i] = Atom(atom_getfloat(argv+i)); + else if(argv[i].a_type == A_SYMBOL) + mess.list[i] = Atom(std::string(atom_getsymbol(argv+i)->s_name)); + } + ptr->m_message_queue.try_enqueue(std::move(mess)); + } + + static void instance_multi_message(pd::Instance* ptr, const char *recv, const char *msg, int argc, t_atom *argv) + { + Message mess{msg, std::vector(argc)}; + for(int i = 0; i < argc; ++i) + { + if(argv[i].a_type == A_FLOAT) + mess.list[i] = Atom(atom_getfloat(argv+i)); + else if(argv[i].a_type == A_SYMBOL) + mess.list[i] = Atom(std::string(atom_getsymbol(argv+i)->s_name)); + } + ptr->m_message_queue.try_enqueue(std::move(mess)); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + static void instance_multi_noteon(pd::Instance* ptr, int channel, int pitch, int velocity) + { + ptr->m_midi_queue.try_enqueue({midievent::NOTEON, channel, pitch, velocity}); + } + + static void instance_multi_controlchange(pd::Instance* ptr, int channel, int controller, int value) + { + ptr->m_midi_queue.try_enqueue({midievent::CONTROLCHANGE, channel, controller, value}); + } + + static void instance_multi_programchange(pd::Instance* ptr, int channel, int value) + { + ptr->m_midi_queue.try_enqueue({midievent::PROGRAMCHANGE, channel, value, 0}); + } + + static void instance_multi_pitchbend(pd::Instance* ptr, int channel, int value) + { + ptr->m_midi_queue.try_enqueue({midievent::PITCHBEND, channel, value, 0}); + } + + static void instance_multi_aftertouch(pd::Instance* ptr, int channel, int value) + { + ptr->m_midi_queue.try_enqueue({midievent::AFTERTOUCH, channel, value, 0}); + } + + static void instance_multi_polyaftertouch(pd::Instance* ptr, int channel, int pitch, int value) + { + ptr->m_midi_queue.try_enqueue({midievent::POLYAFTERTOUCH, channel, pitch, value}); + } + + static void instance_multi_midibyte(pd::Instance* ptr, int port, int byte) + { + ptr->m_midi_queue.try_enqueue({midievent::MIDIBYTE, port, byte, 0}); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + static void instance_multi_print(pd::Instance* ptr, char const* s) + { + ptr->m_print_queue.try_enqueue(std::string(s)); + } + }; + +} + +namespace pd +{ + ////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + Instance::Instance(std::string const& symbol) + { + libpd_multi_init(); + m_instance = libpd_new_instance(); + libpd_set_instance(static_cast(m_instance)); + m_midi_receiver = libpd_multi_midi_new(this, + reinterpret_cast(internal::instance_multi_noteon), + reinterpret_cast(internal::instance_multi_controlchange), + reinterpret_cast(internal::instance_multi_programchange), + reinterpret_cast(internal::instance_multi_pitchbend), + reinterpret_cast(internal::instance_multi_aftertouch), + reinterpret_cast(internal::instance_multi_polyaftertouch), + reinterpret_cast(internal::instance_multi_midibyte)); + m_print_receiver = libpd_multi_print_new(this, + reinterpret_cast(internal::instance_multi_print)); + + m_message_receiver = libpd_multi_receiver_new(this, symbol.c_str(), + reinterpret_cast(internal::instance_multi_bang), + reinterpret_cast(internal::instance_multi_float), + reinterpret_cast(internal::instance_multi_symbol), + reinterpret_cast(internal::instance_multi_list), + reinterpret_cast(internal::instance_multi_message)); + m_atoms = malloc(sizeof(t_atom) * 512); + } + + Instance::~Instance() + { + closePatch(); + pd_free((t_pd *)m_midi_receiver); + pd_free((t_pd *)m_print_receiver); + pd_free((t_pd *)m_message_receiver); + libpd_set_instance(static_cast(m_instance)); + libpd_free_instance(static_cast(m_instance)); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + int Instance::getBlockSize() const noexcept + { + return libpd_blocksize(); + } + + void Instance::prepareDSP(const int nins, const int nouts, const double samplerate) + { + libpd_set_instance(static_cast(m_instance)); + libpd_init_audio(nins, nouts, (int)samplerate); + } + + void Instance::startDSP() + { + t_atom av; + libpd_set_float(&av, 1.f); + libpd_message("pd", "dsp", 1, &av); + } + + void Instance::releaseDSP() + { + t_atom av; + libpd_set_instance(static_cast(m_instance)); + libpd_set_float(&av, 0.f); + libpd_message("pd", "dsp", 1, &av); + } + + void Instance::performDSP(float const* inputs, float* outputs) + { + libpd_set_instance(static_cast(m_instance)); + libpd_process_raw(inputs, outputs); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + void Instance::sendNoteOn(const int channel, const int pitch, const int velocity) const + { + libpd_set_instance(static_cast(m_instance)); + libpd_noteon(channel-1, pitch, velocity); + } + + void Instance::sendControlChange(const int channel, const int controller, const int value) const + { + libpd_set_instance(static_cast(m_instance)); + libpd_controlchange(channel-1, controller, value); + } + + void Instance::sendProgramChange(const int channel, const int value) const + { + libpd_set_instance(static_cast(m_instance)); + libpd_programchange(channel-1, value); + } + + void Instance::sendPitchBend(const int channel, const int value) const + { + libpd_set_instance(static_cast(m_instance)); + libpd_pitchbend(channel-1, value); + } + + void Instance::sendAfterTouch(const int channel, const int value) const + { + libpd_set_instance(static_cast(m_instance)); + libpd_aftertouch(channel-1, value); + } + + void Instance::sendPolyAfterTouch(const int channel, const int pitch, const int value) const + { + libpd_set_instance(static_cast(m_instance)); + libpd_polyaftertouch(channel-1, pitch, value); + } + + void Instance::sendSysEx(const int port, const int byte) const + { + libpd_set_instance(static_cast(m_instance)); + libpd_sysex(port, byte); + } + + void Instance::sendSysRealTime(const int port, const int byte) const + { + libpd_set_instance(static_cast(m_instance)); + libpd_sysrealtime(port, byte); + } + + void Instance::sendMidiByte(const int port, const int byte) const + { + libpd_set_instance(static_cast(m_instance)); + libpd_midibyte(port, byte); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + void Instance::sendBang(std::string const& receiver) const + { + libpd_set_instance(static_cast(m_instance)); + libpd_bang(receiver.c_str()); + } + + void Instance::sendFloat(std::string const& receiver, float const value) const + { + libpd_set_instance(static_cast(m_instance)); + libpd_float(receiver.c_str(), value); + } + + void Instance::sendSymbol(std::string const& receiver, std::string const& symbol) const + { + libpd_set_instance(static_cast(m_instance)); + libpd_symbol(receiver.c_str(), symbol.c_str()); + } + + void Instance::sendList(std::string const& receiver, const std::vector& list) const + { + t_atom* argv = static_cast(m_atoms); + libpd_set_instance(static_cast(m_instance)); + for(size_t i = 0; i < list.size(); ++i) + { + if(list[i].isFloat()) + libpd_set_float(argv+i, list[i].getFloat()); + else + libpd_set_symbol(argv+i, list[i].getSymbol().c_str()); + } + libpd_list(receiver.c_str(), (int)list.size(), argv); + } + + void Instance::sendMessage(std::string const& receiver, const std::string& msg, const std::vector& list) const + { + t_atom* argv = static_cast(m_atoms); + libpd_set_instance(static_cast(m_instance)); + for(size_t i = 0; i < list.size(); ++i) + { + if(list[i].isFloat()) + libpd_set_float(argv+i, list[i].getFloat()); + else + libpd_set_symbol(argv+i, list[i].getSymbol().c_str()); + } + libpd_message(receiver.c_str(), msg.c_str(), (int)list.size(), argv); + } + + void Instance::processMessages() + { + Message mess; + while(m_message_queue.try_dequeue(mess)) + { + if(mess.selector == std::string("bang")) + receiveBang(); + else if(mess.selector == std::string("float")) + receiveFloat(mess.list[0].getFloat()); + else if(mess.selector == std::string("symbol")) + receiveSymbol(mess.list[0].getSymbol()); + else if(mess.selector == std::string("list")) + receiveList(mess.list); + else + receiveMessage(mess.selector, mess.list); + } + } + + void Instance::processMidi() + { + midievent event; + while(m_midi_queue.try_dequeue(event)) + { + if(event.type == midievent::NOTEON) + receiveNoteOn(event.midi1+1, event.midi2, event.midi3); + else if(event.type == midievent::CONTROLCHANGE) + receiveControlChange(event.midi1+1, event.midi2, event.midi3); + else if(event.type == midievent::PROGRAMCHANGE) + receiveProgramChange(event.midi1+1, event.midi2); + else if(event.type == midievent::PITCHBEND) + receivePitchBend(event.midi1+1, event.midi2); + else if(event.type == midievent::AFTERTOUCH) + receiveAftertouch(event.midi1+1, event.midi2); + else if(event.type == midievent::POLYAFTERTOUCH) + receivePolyAftertouch(event.midi1+1, event.midi2, event.midi3); + else if(event.type == midievent::MIDIBYTE) + receiveMidiByte(event.midi1, event.midi2); + } + } + + void Instance::processPrints() + { + std::string temp; + std::string print; + while(m_print_queue.try_dequeue(print)) + { + if(print.back() == '\n') + { + while(print.back() == '\n' || print.back() == ' ') { + print.pop_back(); + } + temp += print; + receivePrint(temp); + temp.clear(); + } + else + { + temp += print; + } + } + } + + void Instance::enqueueMessages(const std::string& dest, const std::string& msg, std::vector&& list) + { + m_send_queue.try_enqueue(dmessage{nullptr, dest, msg, std::move(list)}); + messageEnqueued(); + } + + void Instance::enqueueDirectMessages(void* object, const std::string& msg) + { + m_send_queue.try_enqueue(dmessage{object, std::string(), std::string(), std::vector(1, msg)}); + messageEnqueued(); + } + + void Instance::enqueueDirectMessages(void* object, const float msg) + { + m_send_queue.try_enqueue(dmessage{object, std::string(), std::string(), std::vector(1, msg)}); + messageEnqueued(); + } + + void Instance::dequeueMessages() + { + libpd_set_instance(static_cast(m_instance)); + dmessage mess; + while(m_send_queue.try_dequeue(mess)) + { + if(mess.object && !mess.list.empty()) + { + if(mess.list[0].isFloat()) + { + sys_lock(); + pd_float(static_cast(mess.object), mess.list[0].getFloat()); + sys_unlock(); + } + else + { + sys_lock(); + pd_symbol(static_cast(mess.object), gensym(mess.list[0].getSymbol().c_str())); + sys_unlock(); + } + } + else + { + sendMessage(mess.destination, mess.selector, mess.list); + } + } + } + + ////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + void Instance::openPatch(std::string const& path, std::string const& name) + { + closePatch(); + libpd_set_instance(static_cast(m_instance)); + m_patch = libpd_create_canvas(name.c_str(), path.c_str()); + + } + + void Instance::closePatch() + { + if(m_patch) + { + libpd_set_instance(static_cast(m_instance)); + libpd_closefile(m_patch); + m_patch = nullptr; + } + } + + Patch Instance::getPatch() + { + return Patch(m_patch, this); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + Array Instance::getArray(std::string const& name) + { + return Array(name, m_instance); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + void Instance::setThis() + { + libpd_set_instance(static_cast(m_instance)); + } + +} + diff --git a/ports/camomile/source/Pd/PdInstance.hpp b/ports/camomile/source/Pd/PdInstance.hpp new file mode 100644 index 00000000..d7761285 --- /dev/null +++ b/ports/camomile/source/Pd/PdInstance.hpp @@ -0,0 +1,137 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + +#pragma once + +#include +#include +#include "PdPatch.hpp" +#include "PdAtom.hpp" + +#include "../Queues/readerwriterqueue.h" +#include "../Queues/concurrentqueue.h" + +namespace pd +{ + class Patch; + // ==================================================================================== // + // INSTANCE // + // ==================================================================================== // + + class Instance + { + public: + + Instance(std::string const& symbol); + Instance(Instance const& other) = delete; + virtual ~Instance(); + + void prepareDSP(const int nins, const int nouts, const double samplerate); + void startDSP(); + void releaseDSP(); + void performDSP(float const* inputs, float* outputs); + int getBlockSize() const noexcept; + + void sendNoteOn(const int channel, const int pitch, const int velocity) const; + void sendControlChange(const int channel, const int controller, const int value) const; + void sendProgramChange(const int channel, const int value) const; + void sendPitchBend(const int channel, const int value) const; + void sendAfterTouch(const int channel, const int value) const; + void sendPolyAfterTouch(const int channel, const int pitch, const int value) const; + void sendSysEx(const int port, const int byte) const; + void sendSysRealTime(const int port, const int byte) const; + void sendMidiByte(const int port, const int byte) const; + + virtual void receiveNoteOn(const int channel, const int pitch, const int velocity) {} + virtual void receiveControlChange(const int channel, const int controller, const int value) {} + virtual void receiveProgramChange(const int channel, const int value) {} + virtual void receivePitchBend(const int channel, const int value) {} + virtual void receiveAftertouch(const int channel, const int value) {} + virtual void receivePolyAftertouch(const int channel, const int pitch, const int value) {} + virtual void receiveMidiByte(const int port, const int byte) {} + + void sendBang(std::string const& receiver) const; + void sendFloat(std::string const& receiver, float const value) const; + void sendSymbol(std::string const& receiver, std::string const& symbol) const; + void sendList(std::string const& receiver, const std::vector& list) const; + void sendMessage(std::string const& receiver, const std::string& msg, const std::vector& list) const; + + virtual void receivePrint(const std::string& message) {}; + + virtual void receiveBang() {} + virtual void receiveFloat(float num) {} + virtual void receiveSymbol(const std::string& symbol) {} + virtual void receiveList(const std::vector& list) {} + virtual void receiveMessage(const std::string& msg, const std::vector& list) {} + + void enqueueMessages(const std::string& dest, const std::string& msg, std::vector&& list); + void enqueueDirectMessages(void* object, const std::string& msg); + void enqueueDirectMessages(void* object, const float msg); + + virtual void messageEnqueued() {}; + + void dequeueMessages(); + void processMessages(); + void processPrints(); + void processMidi(); + + void openPatch(std::string const& path, std::string const& name); + void closePatch(); + Patch getPatch(); + + void setThis(); + Array getArray(std::string const& name); + + private: + + void* m_instance = nullptr; + void* m_patch = nullptr; + void* m_atoms = nullptr; + void* m_message_receiver = nullptr; + void* m_midi_receiver = nullptr; + void* m_print_receiver = nullptr; + + struct Message + { + std::string selector; + std::vector list; + }; + + struct dmessage + { + void* object; + std::string destination; + std::string selector; + std::vector list; + }; + + typedef struct midievent + { + enum + { + NOTEON, + CONTROLCHANGE, + PROGRAMCHANGE, + PITCHBEND, + AFTERTOUCH, + POLYAFTERTOUCH, + MIDIBYTE + } type; + int midi1; + int midi2; + int midi3; + } midievent; + + typedef moodycamel::ConcurrentQueue message_queue; + message_queue m_send_queue = message_queue(4096); + + moodycamel::ConcurrentQueue m_message_queue = moodycamel::ConcurrentQueue(4096); + moodycamel::ConcurrentQueue m_midi_queue = moodycamel::ConcurrentQueue(4096); + moodycamel::ConcurrentQueue m_print_queue = moodycamel::ConcurrentQueue(4096); + + struct internal; + }; +} diff --git a/ports/camomile/source/Pd/PdObject.cpp b/ports/camomile/source/Pd/PdObject.cpp new file mode 100755 index 00000000..ff143f9b --- /dev/null +++ b/ports/camomile/source/Pd/PdObject.cpp @@ -0,0 +1,70 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + +#include "PdObject.hpp" +#include "PdInstance.hpp" +extern "C" +{ +#include "x_libpd_extra_utils.h" +} + +namespace pd +{ + // ==================================================================================== // + // OBJECT // + // ==================================================================================== // + + Object::Object(void* ptr, void* patch, Instance* instance) noexcept : + m_ptr(ptr), m_patch(patch), m_instance(instance) + { + } + + std::string Object::getText() const + { + if(m_ptr) + { + char* text = nullptr; + int size = 0; + m_instance->setThis(); + libpd_get_object_text(m_ptr, &text, &size); + if(text && size) + { + std::string txt(text, size); + freebytes(static_cast(text), static_cast(size) * sizeof(char)); + return txt; + } + } + return std::string(); + } + + std::string Object::getName() const + { + if(m_ptr) + { + char const* name = libpd_get_object_class_name(m_ptr); + if(name) + { + return std::string(name); + } + } + return std::string(); + } + + std::array Object::getBounds() const noexcept + { + if(m_ptr) + { + int x = 0, y = 0, w = 0, h = 0; + m_instance->setThis(); + libpd_get_object_bounds(m_patch, m_ptr, &x, &y, &w, &h); + return {x, y, w, h}; + } + return {0, 0, 0, 0}; + } +} + + + diff --git a/ports/camomile/source/Pd/PdObject.hpp b/ports/camomile/source/Pd/PdObject.hpp new file mode 100755 index 00000000..accbf5a2 --- /dev/null +++ b/ports/camomile/source/Pd/PdObject.hpp @@ -0,0 +1,58 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ +#pragma once + +#include +#include +#include + +namespace pd +{ + class Patch; + class Instance; + // ==================================================================================== // + // OBJECT // + // ==================================================================================== // + + //! @brief The Pd object. + //! @details The class is a wrapper around a Pd object. The lifetime of the internal\n + //! object is not guaranteed by the class. + //! @see Instance, Patch, Gui + class Object + { + public: + + //! @brief The default constructor. + Object() noexcept = default; + + //! @brief The copy constructor. + Object(Object const& other) noexcept = default; + + //! @brief The copy operator. + Object& operator=(Object const& other) noexcept = default; + + //! @brief The destructor. + virtual ~Object() noexcept = default; + + //! @brief The text of the Object. + std::string getText() const; + + //! @brief The name of the Object. + std::string getName() const; + + //! @brief The bounds of the Object. + virtual std::array getBounds() const noexcept; + + protected: + Object(void* ptr, void* patch, Instance* instance) noexcept; + + void* m_ptr = nullptr; + void* m_patch = nullptr; + Instance* m_instance = nullptr; + friend class Patch; + }; +} + diff --git a/ports/camomile/source/Pd/PdPatch.cpp b/ports/camomile/source/Pd/PdPatch.cpp new file mode 100644 index 00000000..26e74056 --- /dev/null +++ b/ports/camomile/source/Pd/PdPatch.cpp @@ -0,0 +1,73 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + +#include "PdPatch.hpp" +#include "PdObject.hpp" +#include "PdGui.hpp" + +extern "C" +{ +#include +#include +#include +#include "x_libpd_multi.h" +} + +namespace pd +{ + // ==================================================================================== // + // PATCHER // + // ==================================================================================== // + + Patch::Patch(void* ptr, Instance* instance) noexcept : + m_ptr(ptr), m_instance(instance) + { + } + + bool Patch::isGraph() const noexcept + { + if(m_ptr) + { + return static_cast(static_cast(m_ptr)->gl_isgraph); + } + return false; + } + + std::array Patch::getBounds() const noexcept + { + if(m_ptr) + { + t_canvas const* cnv = static_cast(m_ptr); + if(cnv->gl_isgraph) + { + return {cnv->gl_xmargin, cnv->gl_ymargin, cnv->gl_pixwidth - 2, cnv->gl_pixheight - 2}; + } + } + return {0, 0, 0, 0}; + } + + std::vector Patch::getGuis() noexcept + { + if(m_ptr) + { + std::vector objects; + t_canvas const* cnv = static_cast(m_ptr); + for(t_gobj *y = cnv->gl_list; y; y = y->g_next) + { + Gui gui(static_cast(y), m_ptr, m_instance); + if(gui.getType() != Gui::Type::Undefined) + { + objects.push_back(gui); + } + } + return objects; + } + return std::vector(); + } +} + + + diff --git a/ports/camomile/source/Pd/PdPatch.hpp b/ports/camomile/source/Pd/PdPatch.hpp new file mode 100644 index 00000000..2fd0a42b --- /dev/null +++ b/ports/camomile/source/Pd/PdPatch.hpp @@ -0,0 +1,55 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ +#pragma once + +#include "PdGui.hpp" +#include +#include + +namespace pd +{ + class Instance; + // ==================================================================================== // + // PATCHER // + // ==================================================================================== // + + //! @brief The Pd patch. + //! @details The class is a wrapper around a Pd patch. The lifetime of the internal patch\n + //! is not guaranteed by the class. + //! @see Instance, Object, Gui + class Patch + { + public: + //! @brief The default constructor. + Patch() noexcept = default; + + //! @brief The copy constructor. + Patch(const Patch&) noexcept = default; + + //! @brief The copy operator. + Patch& operator=(const Patch& other) noexcept = default; + + //! @brief The destructor. + ~Patch() noexcept = default; + + //! @brief Gets if the patch is Graph On Parent. + bool isGraph() const noexcept; + + //! @brief Gets the bounds of the patch. + std::array getBounds() const noexcept; + + //! @brief Gets the GUI objects of the patch. + std::vector getGuis() noexcept; + private: + Patch(void* ptr, Instance* instance) noexcept; + + void* m_ptr = nullptr; + Instance* m_instance = nullptr; + + friend class Instance; + friend class Gui; + }; +} diff --git a/ports/camomile/source/Pd/x_libpd_extra_utils.c b/ports/camomile/source/Pd/x_libpd_extra_utils.c new file mode 100644 index 00000000..1647cc6a --- /dev/null +++ b/ports/camomile/source/Pd/x_libpd_extra_utils.c @@ -0,0 +1,152 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" +#include "g_all_guis.h" +#include "x_libpd_multi.h" + +// False GARRAY +typedef struct _fake_garray +{ + t_gobj x_gobj; + t_scalar *x_scalar; + t_glist *x_glist; + t_symbol *x_name; + t_symbol *x_realname; + char x_usedindsp; + char x_saveit; + char x_listviewing; + char x_hidename; +} t_fake_garray; + +void* libpd_create_canvas(const char* name, const char* path) +{ + t_canvas* cnv = (t_canvas *)libpd_openfile(name, path); + if(cnv) + { + canvas_vis(cnv, 1.f); + } + return cnv; +} + +char const* libpd_get_object_class_name(void* ptr) +{ + return class_getname(pd_class((t_pd*)ptr)); +} + +void libpd_get_object_text(void* ptr, char** text, int* size) +{ + *text = NULL; *size = 0; + binbuf_gettext(((t_text*)ptr)->te_binbuf, text, size); +} + +void libpd_get_object_bounds(void* patch, void* ptr, int* x, int* y, int* w, int* h) +{ + t_canvas *cnv = (t_canvas*)glist_getcanvas(patch); + *x = 0; *y = 0; *w = 0; *h = 0; + gobj_getrect((t_gobj *)ptr, cnv, x, y, w, h); + *x -= 1; + *y -= 1; + *w -= *x; + *h -= *y; +} + +t_fake_garray* libpd_array_get_byname(char const* name) +{ + return (t_fake_garray *)pd_findbyclass(gensym((char *)name), garray_class); +} + +char const* libpd_array_get_name(void* ptr) +{ + return ((t_fake_garray*)ptr)->x_realname->s_name; +} + +void libpd_array_get_scale(char const* name, float* min, float* max) +{ + t_canvas const *cnv; + t_fake_garray const *array = libpd_array_get_byname(name); + if(array) + { + cnv = ((t_fake_garray*)array)->x_glist; + if(cnv) + { + *min = cnv->gl_y2; + *max = cnv->gl_y1; + return; + } + } + *min = -1; + *max = 1; +} + +int libpd_array_get_style(char const* name) +{ + t_fake_garray const *array = libpd_array_get_byname(name); + if(array && array->x_scalar) + { + t_scalar *scalar = array->x_scalar; + t_template *scalartplte = template_findbyname(scalar->sc_template); + if(scalartplte) + { + return (int)template_getfloat(scalartplte, gensym("style"), scalar->sc_vec, 0); + } + } + return 0; +} + + + + +static unsigned int convert_from_iem_color(int const color) +{ + unsigned int const c = (unsigned int)(color << 8 | 0xFF); + return ((0xFF << 24) | ((c >> 24) << 16) | ((c >> 16) << 8) | (c >> 8)); +} + +unsigned int libpd_iemgui_get_background_color(void* ptr) +{ + return convert_from_iem_color(((t_iemgui*)ptr)->x_bcol); +} + +unsigned int libpd_iemgui_get_foreground_color(void* ptr) +{ + return convert_from_iem_color(((t_iemgui*)ptr)->x_fcol); +} + +float libpd_get_canvas_font_height(t_canvas* cnv) +{ + const int fontsize = glist_getfont(cnv); + const float zoom = (float)glist_getzoom(cnv); + //[8 :8.31571] [10 :9.9651] [12 :11.6403] [16 :16.6228] [24 :23.0142] [36 :36.0032] + if(fontsize == 8) + { + return 8.31571 * zoom; //9.68f * zoom; + } + else if(fontsize == 10) + { + return 9.9651 * zoom; //11.6f * zoom; + } + else if(fontsize == 12) + { + return 11.6403 *zoom; //13.55f * zoom; + } + else if(fontsize == 16) + { + return 16.6228 * zoom; //19.35f * zoom; + } + else if(fontsize == 24) + { + return 23.0142 * zoom; //26.79f * zoom; + } + else if(fontsize == 36) + { + return 36.0032 * zoom; //41.91f * zoom; + } + return glist_fontheight(cnv); +} + diff --git a/ports/camomile/source/Pd/x_libpd_extra_utils.h b/ports/camomile/source/Pd/x_libpd_extra_utils.h new file mode 100644 index 00000000..9ec2ff90 --- /dev/null +++ b/ports/camomile/source/Pd/x_libpd_extra_utils.h @@ -0,0 +1,37 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + +#ifndef __X_LIBPD_EXTRA_UTILS_H__ +#define __X_LIBPD_EXTRA_UTILS_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + void* libpd_create_canvas(const char* name, const char* path); + + char const* libpd_get_object_class_name(void* ptr); + void libpd_get_object_text(void* ptr, char** text, int* size); + void libpd_get_object_bounds(void* patch, void* ptr, int* x, int* y, int* w, int* h); + + + char const* libpd_array_get_name(void* ptr); + void libpd_array_get_scale(char const* name, float* min, float* max); + int libpd_array_get_style(char const* name); + + unsigned int libpd_iemgui_get_background_color(void* ptr); + unsigned int libpd_iemgui_get_foreground_color(void* ptr); + + float libpd_get_canvas_font_height(t_canvas* cnv); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ports/camomile/source/Pd/x_libpd_multi.c b/ports/camomile/source/Pd/x_libpd_multi.c new file mode 100644 index 00000000..279606fe --- /dev/null +++ b/ports/camomile/source/Pd/x_libpd_multi.c @@ -0,0 +1,335 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + +#include +#include +#include +#include "x_libpd_multi.h" + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// + +static t_class *libpd_multi_receiver_class; + +typedef struct _libpd_multi_receiver +{ + t_object x_obj; + t_symbol* x_sym; + void* x_ptr; + + t_libpd_multi_banghook x_hook_bang; + t_libpd_multi_floathook x_hook_float; + t_libpd_multi_symbolhook x_hook_symbol; + t_libpd_multi_listhook x_hook_list; + t_libpd_multi_messagehook x_hook_message; +} t_libpd_multi_receiver; + +static void libpd_multi_receiver_bang(t_libpd_multi_receiver *x) +{ + if(x->x_hook_bang) + x->x_hook_bang(x->x_ptr, x->x_sym->s_name); +} + +static void libpd_multi_receiver_float(t_libpd_multi_receiver *x, t_float f) +{ + if(x->x_hook_float) + x->x_hook_float(x->x_ptr, x->x_sym->s_name, f); +} + +static void libpd_multi_receiver_symbol(t_libpd_multi_receiver *x, t_symbol *s) +{ + if(x->x_hook_symbol) + x->x_hook_symbol(x->x_ptr, x->x_sym->s_name, s->s_name); +} + +static void libpd_multi_receiver_list(t_libpd_multi_receiver *x, t_symbol *s, int argc, t_atom *argv) +{ + if(x->x_hook_list) + x->x_hook_list(x->x_ptr, x->x_sym->s_name, argc, argv); +} + +static void libpd_multi_receiver_anything(t_libpd_multi_receiver *x, t_symbol *s, int argc, t_atom *argv) +{ + if(x->x_hook_message) + x->x_hook_message(x->x_ptr, x->x_sym->s_name, s->s_name, argc, argv); +} + +static void libpd_multi_receiver_free(t_libpd_multi_receiver *x) +{ + pd_unbind(&x->x_obj.ob_pd, x->x_sym); +} + +static void libpd_multi_receiver_setup(void) +{ + sys_lock(); + libpd_multi_receiver_class = class_new(gensym("libpd_multi_receiver"), (t_newmethod)NULL, (t_method)libpd_multi_receiver_free, + sizeof(t_libpd_multi_receiver), CLASS_DEFAULT, A_NULL, 0); + class_addbang(libpd_multi_receiver_class, libpd_multi_receiver_bang); + class_addfloat(libpd_multi_receiver_class,libpd_multi_receiver_float); + class_addsymbol(libpd_multi_receiver_class, libpd_multi_receiver_symbol); + class_addlist(libpd_multi_receiver_class, libpd_multi_receiver_list); + class_addanything(libpd_multi_receiver_class, libpd_multi_receiver_anything); + sys_unlock(); +} + +void* libpd_multi_receiver_new(void* ptr, char const *s, + t_libpd_multi_banghook hook_bang, + t_libpd_multi_floathook hook_float, + t_libpd_multi_symbolhook hook_symbol, + t_libpd_multi_listhook hook_list, + t_libpd_multi_messagehook hook_message) +{ + + t_libpd_multi_receiver *x = (t_libpd_multi_receiver *)pd_new(libpd_multi_receiver_class); + if(x) + { + sys_lock(); + x->x_sym = gensym(s); + sys_unlock(); + pd_bind(&x->x_obj.ob_pd, x->x_sym); + x->x_ptr = ptr; + x->x_hook_bang = hook_bang; + x->x_hook_float = hook_float; + x->x_hook_symbol = hook_symbol; + x->x_hook_list = hook_list; + x->x_hook_message = hook_message; + } + return x; +} + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// + +static t_class *libpd_multi_midi_class; + +typedef struct _libpd_multi_midi +{ + t_object x_obj; + void* x_ptr; + + t_libpd_multi_noteonhook x_hook_noteon; + t_libpd_multi_controlchangehook x_hook_controlchange; + t_libpd_multi_programchangehook x_hook_programchange; + t_libpd_multi_pitchbendhook x_hook_pitchbend; + t_libpd_multi_aftertouchhook x_hook_aftertouch; + t_libpd_multi_polyaftertouchhook x_hook_polyaftertouch; + t_libpd_multi_midibytehook x_hook_midibyte; +} t_libpd_multi_midi; + +static void libpd_multi_noteon(int channel, int pitch, int velocity) +{ + t_libpd_multi_midi* x = (t_libpd_multi_midi*)gensym("#libpd_multi_midi")->s_thing; + if(x && x->x_hook_noteon) + { + x->x_hook_noteon(x->x_ptr, channel, pitch, velocity); + } +} + +static void libpd_multi_controlchange(int channel, int controller, int value) +{ + t_libpd_multi_midi* x = (t_libpd_multi_midi*)gensym("#libpd_multi_midi")->s_thing; + if(x && x->x_hook_controlchange) + { + x->x_hook_controlchange(x->x_ptr, channel, controller, value); + } +} + +static void libpd_multi_programchange(int channel, int value) +{ + t_libpd_multi_midi* x = (t_libpd_multi_midi*)gensym("#libpd_multi_midi")->s_thing; + if(x && x->x_hook_programchange) + { + x->x_hook_programchange(x->x_ptr, channel, value); + } +} + +static void libpd_multi_pitchbend(int channel, int value) +{ + t_libpd_multi_midi* x = (t_libpd_multi_midi*)gensym("#libpd_multi_midi")->s_thing; + if(x && x->x_hook_pitchbend) + { + x->x_hook_pitchbend(x->x_ptr, channel, value); + } +} + +static void libpd_multi_aftertouch(int channel, int value) +{ + t_libpd_multi_midi* x = (t_libpd_multi_midi*)gensym("#libpd_multi_midi")->s_thing; + if(x && x->x_hook_aftertouch) + { + x->x_hook_aftertouch(x->x_ptr, channel, value); + } +} + +static void libpd_multi_polyaftertouch(int channel, int pitch, int value) +{ + t_libpd_multi_midi* x = (t_libpd_multi_midi*)gensym("#libpd_multi_midi")->s_thing; + if(x && x->x_hook_polyaftertouch) + { + x->x_hook_polyaftertouch(x->x_ptr, channel, pitch, value); + } +} + +static void libpd_multi_midibyte(int port, int byte) +{ + t_libpd_multi_midi* x = (t_libpd_multi_midi*)gensym("#libpd_multi_midi")->s_thing; + if(x && x->x_hook_midibyte) + { + x->x_hook_midibyte(x->x_ptr, port, byte); + } +} + +static void libpd_multi_midi_free(t_libpd_multi_midi *x) +{ + pd_unbind(&x->x_obj.ob_pd, gensym("#libpd_multi_midi")); +} + +static void libpd_multi_midi_setup(void) +{ + sys_lock(); + libpd_multi_midi_class = class_new(gensym("libpd_multi_midi"), (t_newmethod)NULL, (t_method)libpd_multi_midi_free, + sizeof(t_libpd_multi_midi), CLASS_DEFAULT, A_NULL, 0); + sys_unlock(); +} + +void* libpd_multi_midi_new(void* ptr, + t_libpd_multi_noteonhook hook_noteon, + t_libpd_multi_controlchangehook hook_controlchange, + t_libpd_multi_programchangehook hook_programchange, + t_libpd_multi_pitchbendhook hook_pitchbend, + t_libpd_multi_aftertouchhook hook_aftertouch, + t_libpd_multi_polyaftertouchhook hook_polyaftertouch, + t_libpd_multi_midibytehook hook_midibyte) +{ + + t_libpd_multi_midi *x = (t_libpd_multi_midi *)pd_new(libpd_multi_midi_class); + if(x) + { + sys_lock(); + t_symbol* s = gensym("#libpd_multi_midi"); + sys_unlock(); + pd_bind(&x->x_obj.ob_pd, s); + x->x_ptr = ptr; + x->x_hook_noteon = hook_noteon; + x->x_hook_controlchange = hook_controlchange; + x->x_hook_programchange = hook_programchange; + x->x_hook_pitchbend = hook_pitchbend; + x->x_hook_aftertouch = hook_aftertouch; + x->x_hook_polyaftertouch= hook_polyaftertouch; + x->x_hook_midibyte = hook_midibyte; + } + return x; +} + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// + +static t_class *libpd_multi_print_class; + +typedef struct _libpd_multi_print +{ + t_object x_obj; + void* x_ptr; + t_libpd_multi_printhook x_hook; +} t_libpd_multi_print; + +static void libpd_multi_print(const char* message) +{ + t_libpd_multi_print* x = (t_libpd_multi_print*)gensym("#libpd_multi_print")->s_thing; + if(x && x->x_hook) + { + x->x_hook(x->x_ptr, message); + } +} + +static void libpd_multi_print_setup(void) +{ + sys_lock(); + libpd_multi_print_class = class_new(gensym("libpd_multi_print"), (t_newmethod)NULL, (t_method)NULL, + sizeof(t_libpd_multi_print), CLASS_DEFAULT, A_NULL, 0); + sys_unlock(); +} + +void* libpd_multi_print_new(void* ptr, t_libpd_multi_printhook hook_print) +{ + + t_libpd_multi_print *x = (t_libpd_multi_print *)pd_new(libpd_multi_print_class); + if(x) + { + sys_lock(); + t_symbol* s = gensym("#libpd_multi_print"); + sys_unlock(); + pd_bind(&x->x_obj.ob_pd, s); + x->x_ptr = ptr; + x->x_hook = hook_print; + } + return x; +} + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +// + +// font char metric triples: pointsize width(pixels) height(pixels) +static int defaultfontshit[] = { + 8, 5, 11, 10, 6, 13, 12, 7, 16, 16, 10, 19, 24, 14, 29, 36, 22, 44, + 16, 10, 22, 20, 12, 26, 24, 14, 32, 32, 20, 38, 48, 28, 58, 72, 44, 88 +}; // normal & zoomed (2x) +#define NDEFAULTFONT (sizeof(defaultfontshit)/sizeof(*defaultfontshit)) + +static void libpd_defaultfont_init(void) +{ + int i; + t_atom zz[NDEFAULTFONT+2]; + SETSYMBOL(zz, gensym(".")); + SETFLOAT(zz+1,0); + for (i = 0; i < (int)NDEFAULTFONT; i++) + { + SETFLOAT(zz+i+2, defaultfontshit[i]); + } + pd_typedmess(gensym("pd")->s_thing, gensym("init"), 2+NDEFAULTFONT, zz); +} + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// + +void libpd_multi_init(void) +{ + static int initialized = 0; + if(!initialized) + { + libpd_set_noteonhook(libpd_multi_noteon); + libpd_set_controlchangehook(libpd_multi_controlchange); + libpd_set_programchangehook(libpd_multi_programchange); + libpd_set_pitchbendhook(libpd_multi_pitchbend); + libpd_set_aftertouchhook(libpd_multi_aftertouch); + libpd_set_polyaftertouchhook(libpd_multi_polyaftertouch); + libpd_set_midibytehook(libpd_multi_midibyte); + libpd_set_printhook(libpd_multi_print); + + libpd_set_verbose(0); + libpd_init(); + libpd_multi_receiver_setup(); + libpd_multi_midi_setup(); + libpd_multi_print_setup(); + libpd_defaultfont_init(); + libpd_set_verbose(4); + + initialized = 1; + } +} + + diff --git a/ports/camomile/source/Pd/x_libpd_multi.h b/ports/camomile/source/Pd/x_libpd_multi.h new file mode 100644 index 00000000..2188a2d8 --- /dev/null +++ b/ports/camomile/source/Pd/x_libpd_multi.h @@ -0,0 +1,58 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + +#ifndef __X_LIBPD_MULI_H__ +#define __X_LIBPD_MULI_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +void libpd_multi_init(void); + +typedef void (*t_libpd_multi_banghook)(void* ptr, const char *recv); +typedef void (*t_libpd_multi_floathook)(void* ptr, const char *recv, float f); +typedef void (*t_libpd_multi_symbolhook)(void* ptr, const char *recv, const char *s); +typedef void (*t_libpd_multi_listhook)(void* ptr, const char *recv, int argc, t_atom *argv); +typedef void (*t_libpd_multi_messagehook)(void* ptr, const char *recv, const char *msg, int argc, t_atom *argv); + +void* libpd_multi_receiver_new(void* ptr, char const *s, + t_libpd_multi_banghook hook_bang, + t_libpd_multi_floathook hook_float, + t_libpd_multi_symbolhook hook_symbol, + t_libpd_multi_listhook hook_list, + t_libpd_multi_messagehook hook_message); + + +typedef void (*t_libpd_multi_noteonhook)(void* ptr, int channel, int pitch, int velocity); +typedef void (*t_libpd_multi_controlchangehook)(void* ptr, int channel, int controller, int value); +typedef void (*t_libpd_multi_programchangehook)(void* ptr, int channel, int value); +typedef void (*t_libpd_multi_pitchbendhook)(void* ptr, int channel, int value); +typedef void (*t_libpd_multi_aftertouchhook)(void* ptr, int channel, int value); +typedef void (*t_libpd_multi_polyaftertouchhook)(void* ptr, int channel, int pitch, int value); +typedef void (*t_libpd_multi_midibytehook)(void* ptr, int port, int byte); + +void* libpd_multi_midi_new(void* ptr, + t_libpd_multi_noteonhook hook_noteon, + t_libpd_multi_controlchangehook hook_controlchange, + t_libpd_multi_programchangehook hook_programchange, + t_libpd_multi_pitchbendhook hook_pitchbend, + t_libpd_multi_aftertouchhook hook_aftertouch, + t_libpd_multi_polyaftertouchhook hook_polyaftertouch, + t_libpd_multi_midibytehook hook_midibyte); + +typedef void (*t_libpd_multi_printhook)(void* ptr, const char *recv); + +void* libpd_multi_print_new(void* ptr, t_libpd_multi_printhook hook_print); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ports/camomile/source/PluginConfig.h b/ports/camomile/source/PluginConfig.h new file mode 100644 index 00000000..534b9ac6 --- /dev/null +++ b/ports/camomile/source/PluginConfig.h @@ -0,0 +1,22 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. +*/ + +#pragma once + +#include "PluginEnvironment.h" +#define JUCE_DISPLAY_SPLASH_SCREEN 0 +#define JUCE_REPORT_APP_USAGE 0 +#define JucePlugin_Name CamomileEnvironment::getPluginNameUTF8() +#define JucePlugin_PluginCode CamomileEnvironment::getPluginCode() +#define JucePlugin_Desc CamomileEnvironment::getPluginDescriptionUTF8() +#define JucePlugin_LV2URI (juce::String("http://github.com/pierreguillot/Camomile/") + juce::String(JucePlugin_Name)).toUTF8() +#ifndef JucePlugin_Manufacturer +#define JucePlugin_Manufacturer "Pierre Guillot" +#endif + +#ifndef JucePlugin_Build_LV2 +#define JucePlugin_Build_LV2 0 +#endif diff --git a/ports/camomile/source/PluginConsole.h b/ports/camomile/source/PluginConsole.h new file mode 100755 index 00000000..1b8cffe4 --- /dev/null +++ b/ports/camomile/source/PluginConsole.h @@ -0,0 +1,108 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ +#pragma once + +#include +#include +#include +#include +#include +#include + +//! @brief A class that manages the console +class CamomileConsole +{ +public: + public: + using level_t = size_t; + using message_t = std::pair; + + //! @brief the constructor. + CamomileConsole(const level_t maxlevel, size_t const preallocate = 512) : + m_max_level(maxlevel), + m_counters(maxlevel, 0), + m_messages(preallocate) + { + m_messages.clear(); + } + + //! @brief Gets the number of all messages. + size_t size(level_t level) const noexcept + { + assert(level <= m_max_level && "wrong level of message"); + if(m_mutex.try_lock()) + { + size_t size = m_counters[level]; + while (level--) { size += m_counters[level]; } + m_mutex.unlock(); + return size; + } + return 0; + } + + //! @brief Gets a message at an index until a level. + message_t get(level_t level, size_t index) const noexcept + { + assert(level <= m_max_level && "wrong level of message"); + if(m_mutex.try_lock()) + { + for(size_t i = 0, c = 0; i < m_messages.size(); ++i) + { + if(m_messages[i].first <= level) + { + if(c++ == index) + { + m_mutex.unlock(); + return m_messages[i]; + } + } + } + m_mutex.unlock(); + } + return std::pair(); + } + + //! @brief Clears the history. + void clear(level_t level, size_t index = std::numeric_limits::max()) noexcept + { + std::lock_guard guard(m_mutex); + size_t c = 0; + for(auto it = m_messages.begin(); it != m_messages.end(); ++it) + { + if(it->first <= level) + { + if(c++ == index) + { + --m_counters[it->first]; + m_messages.erase(it); + return; + } + } + } + } + + + //! @brief Adds a message to the history. + void add(level_t level, std::string message) noexcept + { + assert(level < m_max_level && "wrong level of message"); + if(m_mutex.try_lock()) + { + if(m_messages.size() < m_messages.capacity()) + { + ++m_counters[level]; + m_messages.push_back(message_t{level, std::move(message)}); + } + m_mutex.unlock(); + } + } + +private: + mutable std::mutex m_mutex; + const level_t m_max_level; + std::vector m_counters; + std::vector m_messages; +}; diff --git a/ports/camomile/source/PluginEditor.cpp b/ports/camomile/source/PluginEditor.cpp new file mode 100644 index 00000000..7c38fe49 --- /dev/null +++ b/ports/camomile/source/PluginEditor.cpp @@ -0,0 +1,139 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ +#include "PluginProcessor.h" +#include "PluginEditor.h" +#include "PluginEnvironment.h" +#include "PluginLookAndFeel.hpp" +#include "Pd/PdPatch.hpp" + +CamomileEditor::CamomileEditor(CamomileAudioProcessor& p) : +AudioProcessorEditor (&p), CamomileEditorInteractionManager(p), m_processor (p), m_button(p) +{ + static CamoLookAndFeel laf; + LookAndFeel::setDefaultLookAndFeel(&laf); + + setOpaque(true); + setWantsKeyboardFocus(true); + setInterceptsMouseClicks(true, true); + m_image.setImage(CamoLookAndFeel::getImage()); + if(m_image.getImage().isNull() && !CamomileEnvironment::getImageName().empty()) + { + m_processor.add(CamomileAudioProcessor::ConsoleLevel::Error, + "background image " + CamomileEnvironment::getImageName() + + " is invalid or doesn't exist."); + } + updatePatch(); + addAndMakeVisible(m_button); + startTimer(25); +} + +CamomileEditor::~CamomileEditor() {} + +void CamomileEditor::updatePatch() +{ + auto const bounds = m_processor.getPatch().getBounds(); + int const width = bounds[2] > 0 ? std::max(bounds[2], 100) : 400; + int const height = bounds[3] > 0 ? std::max(bounds[3], 100) : 300; + if(width != getWidth() || height != getHeight()) + { + setSize(width, height); + if(m_image.getImage().isValid()) + { + m_image.setTransformToFit(getBounds().toType(), RectanglePlacement::fillDestination + RectanglePlacement::xLeft + RectanglePlacement::yTop); + if(!m_image.isVisible()) + { + addAndMakeVisible(m_image, 0); + } + } + } + updateObjects(); +} + +void CamomileEditor::updateObjects() +{ + m_labels.clear(); + m_objects.clear(); + auto const pbounds = m_processor.getPatch().getBounds(); + const auto bounds = getLocalBounds().expanded(2).translated(1, 1); + for(auto& gui : m_processor.getPatch().getGuis()) + { + PluginEditorObject* obj = PluginEditorObject::createTyped(*this, gui); + if(obj) + { + obj->setTopLeftPosition(obj->getX() - pbounds[0], obj->getY() - pbounds[1]); + if(bounds.contains(obj->getBounds())) + { + Component* label = obj->getLabel(); + addAndMakeVisible(m_objects.add(obj)); + if(label) + { + addAndMakeVisible(m_labels.add(label)); + } + } + } + } +} + +void CamomileEditor::timerCallback() +{ + CamomileEditorMessageManager::processMessages(); + for(auto object : m_objects) + { + object->update(); + } +} + + +void CamomileEditor::paint (Graphics& g) +{ + g.fillAll(Colours::white); + if(!CamomileEnvironment::isValid()) + { + g.setColour(Colours::black); + g.drawText("Plugin Not Valid", 0, 0, getWidth(), getHeight(), juce::Justification::centred); + } + else if(!m_processor.getPatch().isGraph()) + { + g.setColour(Colours::black); + g.drawText("No Graphical User Interface Available", 0, 0, getWidth(), getHeight(), juce::Justification::centred); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// + +bool CamomileEditor::keyPressed(const KeyPress& key) +{ + return CamomileEditorKeyManager::keyPressed(key); +} + +bool CamomileEditor::keyStateChanged(bool isKeyDown) +{ + return CamomileEditorKeyManager::keyStateChanged(isKeyDown); +} + +void CamomileEditor::modifierKeysChanged(const ModifierKeys& modifiers) +{ + CamomileEditorKeyManager::keyModifiersChanged(modifiers); +} + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// + +void CamomileEditor::guiResize() +{ + updatePatch(); +} + +void CamomileEditor::guiRedraw() +{ + updateObjects(); +} + + + diff --git a/ports/camomile/source/PluginEditor.h b/ports/camomile/source/PluginEditor.h new file mode 100644 index 00000000..a4b3b41e --- /dev/null +++ b/ports/camomile/source/PluginEditor.h @@ -0,0 +1,41 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + +#pragma once + +#include "PluginProcessor.h" +#include "PluginEditorInteraction.h" +#include "PluginEditorComponents.h" +#include "PluginEditorObject.hpp" + +class CamomileEditor : public AudioProcessorEditor, protected Timer, public CamomileEditorInteractionManager +{ +public: + CamomileEditor(CamomileAudioProcessor&); + ~CamomileEditor(); + void paint(Graphics&) final; + void timerCallback() final; + + ////////////////////////////////////////////////////////////////////////////////////////// + bool keyPressed(const KeyPress& key) final; + bool keyStateChanged(bool isKeyDown) final; + void modifierKeysChanged(const ModifierKeys& modifiers) final; + + void guiResize() final; + void guiRedraw() final; + +private: + void updatePatch(); + void updateObjects(); + + CamomileAudioProcessor& m_processor; + OwnedArray m_objects; + OwnedArray m_labels; + CamomileEditorButton m_button; + DrawableImage m_image; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CamomileEditor) +}; diff --git a/ports/camomile/source/PluginEditorComponents.cpp b/ports/camomile/source/PluginEditorComponents.cpp new file mode 100644 index 00000000..92fd11e8 --- /dev/null +++ b/ports/camomile/source/PluginEditorComponents.cpp @@ -0,0 +1,154 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + +#include "PluginEditorComponents.h" +#include "PluginEditorConsole.hpp" +#include "PluginLookAndFeel.hpp" + +////////////////////////////////////////////////////////////////////////////////////////////// +// ABOUT PATCH // +////////////////////////////////////////////////////////////////////////////////////////////// + +class AboutPatch : public TextEditor +{ +public: + AboutPatch() + { + setMultiLine(true); + setReadOnly(true); + setScrollbarsShown(false); + setCaretVisible(false); + setPopupMenuEnabled(true); + setFont(CamoLookAndFeel::getDefaultFont()); + setWantsKeyboardFocus(true); + setText(CamoLookAndFeel::getDescription()); + } +private: + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AboutPatch) +}; + +////////////////////////////////////////////////////////////////////////////////////////////// +// ABOUT CAMOMILE // +////////////////////////////////////////////////////////////////////////////////////////////// + +class AboutCamomile : public TextEditor +{ +public: + AboutCamomile() + { + setMultiLine(true); + setReadOnly(true); + setScrollbarsShown(false); + setCaretVisible(false); + setPopupMenuEnabled(true); + setFont(CamoLookAndFeel::getDefaultFont()); + setWantsKeyboardFocus(true); + if(PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_AudioUnit) + { + setText(String::createStringFromData(BinaryData::CreditsAU, BinaryData::CreditsAUSize)); + } + else if(PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_VST || + PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_VST3) + { + setText(String::createStringFromData(BinaryData::CreditsVST, BinaryData::CreditsVSTSize)); + } + else // LV2 + { + setText(String::createStringFromData(BinaryData::CreditsLV2, BinaryData::CreditsLV2Size)); + } + } +private: + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AboutCamomile) +}; + +////////////////////////////////////////////////////////////////////////////////////////////// +// WINDOW // +////////////////////////////////////////////////////////////////////////////////////////////// + +class CamomileEditorWindow : public DocumentWindow +{ +public: + CamomileEditorWindow() : DocumentWindow(String(""), Colours::lightgrey, DocumentWindow::closeButton, false) + { + setAlwaysOnTop(true); + setUsingNativeTitleBar(true); + setBounds(50, 50, 300, 370); + setResizable(true, true); + setDropShadowEnabled(true); + setVisible(true); + setWantsKeyboardFocus(true); + } + + void closeButtonPressed() { removeFromDesktop(); } +private: + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CamomileEditorWindow) +}; + +////////////////////////////////////////////////////////////////////////////////////////////// +// BUTTON // +////////////////////////////////////////////////////////////////////////////////////////////// + +CamomileEditorButton::CamomileEditorButton(CamomileAudioProcessor& processor) : Button("CamomileButton"), +m_processor(processor), m_window(new CamomileEditorWindow()) +{ + setClickingTogglesState(false); + setAlwaysOnTop(true); + m_center.setImage(ImageCache::getFromMemory(BinaryData::flower_center_png, BinaryData::flower_center_pngSize)); + m_petals.setImage(ImageCache::getFromMemory(BinaryData::flower_petals_png, BinaryData::flower_petals_pngSize)); + m_center.setTransformToFit(juce::Rectangle(0.f, 0.f, 18.f, 18.f), RectanglePlacement::stretchToFit); + m_petals.setTransformToFit(juce::Rectangle(0.f, 0.f, 18.f, 18.f), RectanglePlacement::stretchToFit); + m_center.setAlwaysOnTop(true); + addAndMakeVisible(m_center, -1); + addAndMakeVisible(m_petals, 0); + m_petals.setOverlayColour(Colours::black); + m_petals.setAlpha(0.5f); + setBounds(3, 3, 18, 18); + + m_window->setBounds(m_processor.getConsoleWindowBounds()); +} + +CamomileEditorButton::~CamomileEditorButton() +{ + m_processor.setConsoleWindowBounds(m_window->getBounds()); +} + +void CamomileEditorButton::buttonStateChanged() +{ + m_petals.setAlpha((isDown() || isOver()) ? 1.f : 0.5f); +} + +void CamomileEditorButton::clicked() +{ + if(m_window->isVisible() && m_window->isShowing()) + { + m_window->toFront(true); + m_window->grabKeyboardFocus(); + if(m_processor.getTrackProperties().name.isNotEmpty()) { + m_window->setName(String(CamomileEnvironment::getPluginName()) + ": " + m_processor.getTrackProperties().name); } + } + else + { + TabbedComponent* tc = new TabbedComponent(TabbedButtonBar::TabsAtTop); + if(tc) + { + tc->setBounds(0, 0, 300, 370); + tc->addTab("Console", Colours::lightgrey, new PluginEditorConsole(m_processor), true); + tc->addTab(CamomileEnvironment::getPluginName(), Colours::lightgrey, new AboutPatch(), true); + tc->addTab("About Camomile", Colours::lightgrey, new AboutCamomile(), true); + tc->setTabBarDepth(24); + + String const trackname = m_processor.getTrackProperties().name; + String const name = String(CamomileEnvironment::getPluginName()) + (trackname.isEmpty() ? "" : trackname); + m_window->setName(name); + m_window->setContentOwned(tc, false); + m_window->addToDesktop(); + m_window->toFront(true); + m_window->grabKeyboardFocus(); + } + + } +} + diff --git a/ports/camomile/source/PluginEditorComponents.h b/ports/camomile/source/PluginEditorComponents.h new file mode 100644 index 00000000..ca23aaaa --- /dev/null +++ b/ports/camomile/source/PluginEditorComponents.h @@ -0,0 +1,32 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. + */ + +#pragma once + +#include "PluginProcessor.h" + +////////////////////////////////////////////////////////////////////////////////////////////// +// BUTTON // +////////////////////////////////////////////////////////////////////////////////////////////// + +//! @brief The flower button +//! The only button of the editor that's not a Pd object. +class CamomileEditorButton : public Button +{ +public: + CamomileEditorButton(CamomileAudioProcessor& processor); + ~CamomileEditorButton(); + void paintButton(Graphics& g, bool over, bool down) final {}; + void buttonStateChanged() final; + void clicked() final; +private: + CamomileAudioProcessor& m_processor; + DrawableImage m_center; + DrawableImage m_petals; + ScopedPointer m_window; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CamomileEditorButton) +}; + diff --git a/ports/camomile/source/PluginEditorConsole.cpp b/ports/camomile/source/PluginEditorConsole.cpp new file mode 100644 index 00000000..8660fadd --- /dev/null +++ b/ports/camomile/source/PluginEditorConsole.cpp @@ -0,0 +1,244 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. +*/ + +#include "PluginEditorConsole.hpp" +#include "PluginLookAndFeel.hpp" + +////////////////////////////////////////////////////////////////////////////////////////////// +// CONSOLE BUTTON // +////////////////////////////////////////////////////////////////////////////////////////////// + +class ConsoleButton : public Button +{ +public: + ConsoleButton(Image const& image) : Button(""), m_image() + { + setClickingTogglesState(false); + setAlwaysOnTop(true); + m_image.setImage(image); + m_image.setTransformToFit(Rectangle(0.f, 0.f, 18.f, 18.f), RectanglePlacement::stretchToFit); + m_image.setAlpha(0.5f); + addAndMakeVisible(m_image); + setSize(18, 18); + } + + void buttonStateChanged() final + { + m_image.setAlpha((isDown() || isOver()) ? 1.f : 0.5f); + } + + void paintButton(Graphics& g, bool over, bool down) final {}; +private: + DrawableImage m_image; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ConsoleButton) +}; + +////////////////////////////////////////////////////////////////////////////////////////////// +// CONSOLE // +////////////////////////////////////////////////////////////////////////////////////////////// + +PluginEditorConsole::PluginEditorConsole(CamomileAudioProcessor& p) : +m_history(p), m_table(), +m_level_button(new ConsoleButton(ImageCache::getFromMemory(BinaryData::settings_png, BinaryData::settings_pngSize))), +m_clear_button(new ConsoleButton(ImageCache::getFromMemory(BinaryData::garbage_png, BinaryData::garbage_pngSize))), +m_copy_button(new ConsoleButton(ImageCache::getFromMemory(BinaryData::copy_png, BinaryData::copy_pngSize))), +m_reload_button(new ConsoleButton(ImageCache::getFromMemory(BinaryData::reload_png, BinaryData::reload_pngSize))), +m_font(CamoLookAndFeel::getDefaultFont().withPointHeight(10.f)) +{ + m_size = 0; + setWantsKeyboardFocus(true); + m_table.setBounds(2, 2, getWidth() - 2, getHeight() - 30); + m_table.setModel(this); + m_table.setOutlineThickness(0); + m_table.setWantsKeyboardFocus(true); + m_table.setMultipleSelectionEnabled(true); + m_table.setMouseMoveSelectsRows(false); + m_table.setRowHeight(static_cast(m_font.getHeight() + 2)); + m_table.setColour(ListBox::ColourIds::backgroundColourId, Colours::transparentWhite); + m_table.getViewport()->setScrollBarsShown(true, true, true, true); + m_table.getViewport()->setScrollBarThickness(4); + addAndMakeVisible(m_table); + + m_clear_button->addListener(this); + addAndMakeVisible(m_clear_button); + m_copy_button->addListener(this); + addAndMakeVisible(m_copy_button); + m_level_button->addListener(this); + addAndMakeVisible(m_level_button); + m_reload_button->addListener(this); + addAndMakeVisible(m_reload_button); + startTimer(100); +} + +PluginEditorConsole::~PluginEditorConsole() +{ + stopTimer(); +} + +void PluginEditorConsole::clearSelection() +{ + stopTimer(); + SparseSet const selection = m_table.getSelectedRows(); + if(selection.isEmpty()) + { + const size_t n = m_history.size(m_level); + for(size_t i = n; i > 0; --i) + { + m_history.clear(m_level, i-1); + } + } + else + { + const int n = selection.size(); + for(int i = n; i > 0; --i) + { + m_history.clear(m_level, static_cast(selection[i-1])); + } + } + m_table.deselectAllRows(); + timerCallback(); + startTimer(100); +} + +void PluginEditorConsole::copySelection() +{ + String text; + stopTimer(); + SparseSet const selection = m_table.getSelectedRows(); + if(selection.isEmpty()) + { + const size_t n = m_history.size(m_level); + for(size_t i = 0; i < n; ++i) + { + text += String(m_history.get(m_level, static_cast(i)).second + "\n"); + } + } + else + { + const int n = selection.size(); + for(int i = 0; i < n; ++i) + { + text += String(m_history.get(m_level, static_cast(selection[i])).second + "\n"); + } + } + SystemClipboard::copyTextToClipboard(text); + startTimer(100); +} + +void PluginEditorConsole::paint(Graphics& g) +{ + g.setColour(Colours::black.withAlpha(0.5f)); + g.drawHorizontalLine(getHeight() - 28, 2.f, static_cast(getWidth()) - 2.f); +} + +void PluginEditorConsole::resized() +{ + const int btn_height = getHeight() - 22; + const int btn_width = 26; + const int btn_woffset = 4; + const int tbl_height = getHeight() - 30; + const int tbl_wdith = getWidth() - 2; + m_level_button->setTopLeftPosition(btn_woffset+btn_width*0, btn_height); + m_clear_button->setTopLeftPosition(btn_woffset+btn_width*1, btn_height); + m_copy_button->setTopLeftPosition(btn_woffset+btn_width*2, btn_height); + m_reload_button->setTopLeftPosition(btn_woffset+btn_width*3, btn_height); + m_table.setSize(tbl_wdith, tbl_height); +} + +bool PluginEditorConsole::keyPressed(const KeyPress& key) +{ + if(key.getModifiers() == ModifierKeys::commandModifier && key.getTextCharacter() == 'c') + { + copySelection(); + return true; + } + return false; +} + +void PluginEditorConsole::deleteKeyPressed(int lastRowSelected) +{ + clearSelection(); +} + +void PluginEditorConsole::buttonClicked(Button* button) +{ + if(button == m_reload_button) + { + m_history.reloadPatch(); + } + else if(button == m_clear_button) + { + clearSelection(); + } + else if(button == m_copy_button) + { + copySelection(); + } + else + { + juce::PopupMenu m; + m.addItem(1, "Fatal", true, m_level == ConsoleLevel::Fatal); + m.addItem(2, "Error", true, m_level == ConsoleLevel::Error); + m.addItem(3, "Normal", true, m_level == ConsoleLevel::Normal); + m.addItem(4, "All", true, m_level == ConsoleLevel::Log); + + stopTimer(); + int const level = m.show(0, 0, static_cast(m_font.getHeight() + 2)); + if(level != 0 && static_cast(level - 1) != m_level) + { + m_level = static_cast(level - 1); + m_size = m_history.size(m_level); + m_table.updateContent(); + m_table.deselectAllRows(); + } + startTimer(100); + } +} + +void PluginEditorConsole::paintListBoxItem(int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) +{ + std::pair const message(m_history.get(m_level, rowNumber)); + if(rowIsSelected) + { + g.setColour(Colours::black); + g.fillRect(0, 0, width, height); + } + + if(message.first == ConsoleLevel::Fatal) + { + g.setColour(Colours::red); + } + else if(message.first == ConsoleLevel::Error) + { + g.setColour(Colours::orange); + } + else if(message.first == ConsoleLevel::Normal) + { + g.setColour(rowIsSelected ? Colours::lightgrey : Colours::black.withAlpha(0.5f)); + } + else + { + g.setColour(Colours::green); + } + String const mess = String(message.second).trimCharactersAtEnd(" \n"); + g.setFont(m_font); + g.drawText(mess, 2, 0, width, height, juce::Justification::centredLeft, 0); +} + +void PluginEditorConsole::timerCallback() +{ + m_history.processPrints(); + const size_t size = m_history.size(m_level); + if(m_size != size) + { + m_size = size; + m_table.updateContent(); + } +} + + + + diff --git a/ports/camomile/source/PluginEditorConsole.hpp b/ports/camomile/source/PluginEditorConsole.hpp new file mode 100755 index 00000000..0ef28059 --- /dev/null +++ b/ports/camomile/source/PluginEditorConsole.hpp @@ -0,0 +1,46 @@ +/* + // Copyright (c) 2015-2018 Pierre Guillot. + // For information on usage and redistribution, and for a DISCLAIMER OF ALL + // WARRANTIES, see the file, "LICENSE.txt," in this distribution. +*/ + +#pragma once + +#include "PluginProcessor.h" + +////////////////////////////////////////////////////////////////////////////////////////////// +// CONSOLE // +////////////////////////////////////////////////////////////////////////////////////////////// + +class PluginEditorConsole : public Component, public Timer, public Button::Listener, public ListBoxModel +{ +public: + PluginEditorConsole(CamomileAudioProcessor& p); + ~PluginEditorConsole(); + void timerCallback() final; + void buttonClicked(Button* button) final; + void paint(Graphics& g) final; + bool keyPressed(const KeyPress& key) final; + void resized() final; + + int getNumRows() final { return static_cast(m_size); } + void paintListBoxItem(int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) final; + void deleteKeyPressed(int lastRowSelected) final; +private: + + void clearSelection(); + void copySelection(); + typedef CamomileAudioProcessor::ConsoleLevel ConsoleLevel; + CamomileAudioProcessor& m_history; + size_t m_size = 0; + ListBox m_table; + ConsoleLevel m_level = ConsoleLevel::Normal; + ScopedPointer